first commit

This commit is contained in:
Ray
2026-02-19 03:37:37 +08:00
commit ccfd8c79a4
2813 changed files with 453657 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
Manifest-Version: 1.0
Class-Path:

View File

@@ -0,0 +1,287 @@
3<%@ page language="java" pageEncoding="utf-8"%>
<%@ include file="include/pagetop.jsp"%>
<!DOCTYPE html>
<html>
<head>
<%@ include file="include/head.jsp"%>
</head>
<body>
<%@ include file="include/loading.jsp"%>
<%@ include file="include/top.jsp"%>
<%@ include file="include/menu_left.jsp"%>
<!-- //////////////////////////////////////////////////////////////////////////// -->
<!-- START CONTENT -->
<div class="content">
<!-- //////////////////////////////////////////////////////////////////////////// -->
<!-- START CONTAINER -->
<div class="container-default">
<h3>提现</h3>
<%@ include file="include/alert.jsp"%>
<!-- //////////////////////////////////////////////////////////////////////////// -->
<!-- START queryForm -->
<div class="row">
<div class="col-md-12">
<div class="panel panel-default">
<div class="panel-title">查询条件</div>
<div class="panel-body">
<form class="form-horizontal"
action="<%=basePath%>normal/adminWithdrawAction!list.action"
method="post" id="queryForm">
<input type="hidden" name="pageNo" id="pageNo"
value="${param.pageNo}">
<s:hidden name="succeeded_para"></s:hidden>
<div class="col-md-12 col-lg-6">
<fieldset>
<div class="control-group">
<div class="controls">
<s:textfield id="name_para" name="name_para"
cssClass="form-control " placeholder="用户" />
</div>
</div>
</fieldset>
</div>
<div class="col-md-12 col-lg-2">
<button type="submit" class="btn btn-light btn-block">查询</button>
</div>
<div class="col-md-12 col-lg-12" style="margin-top: 10px;">
<div class="mailbox clearfix">
<div class="mailbox-menu">
<ul class="menu">
<li><a href="javascript:setState('')"> 全部</a></li>
<li><a href="javascript:setState(0)"> 未处理</a></li>
<li><a href="javascript:setState(1)"> 通过申请</a></li>
<li><a href="javascript:setState(2)"> 驳回申请</a></li>
</ul>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- END queryForm -->
<!-- //////////////////////////////////////////////////////////////////////////// -->
<div class="row">
<div class="col-md-12">
<!-- Start Panel -->
<div class="panel panel-default">
<div class="panel-title">查询结果</div>
<div class="panel-body">
<table class="table table-bordered table-striped">
<thead>
<tr>
<td>用户</td>
<td>数量</td>
<td>手续费</td>
<td>提现方式</td>
<td>货币OTC</td>
<td>到账金额(兑换货币)</td>
<td>账号信息</td>
<td>收款码</td>
<td>状态</td>
<td>驳回原因</td>
<td>时间</td>
<td width="150px"></td>
</tr>
</thead>
<tbody>
<s:iterator value="page.elements" status="stat">
<tr>
<td><s:property value="username" /></td>
<td><fmt:formatNumber value="${volume}" pattern="#0.00" /></td>
<td><fmt:formatNumber value="${amount_fee}"
pattern="#0.00" /></td>
<td><s:property value="method_map.get(method)" /></td>
<td><s:property value="currency" /></td>
<td><fmt:formatNumber value="${amount}" pattern="#0.00" /></td>
<td><s:if test="method=='bank'">
<s:property
value="'[银行]'+bank+'[银行卡号]'+account+'[账户]'+username+'[开户行]'+deposit_bank" />
</s:if> <s:if test="method=='alipay'">
<s:property value="'[账户]'+account+'[姓名]'+username" />
</s:if> <s:if test="method=='weixin'">
<s:property value="'[账户]'+account+'[姓名]'+username" />
</s:if> <s:if test="method=='paypal'">
<s:property value="'[账户]'+account+'[姓名]'+username" />
</s:if> <s:if test="channel=='usdt'">
[区块链地址]<s:property value="address" />
</s:if></td>
<td></td>
<td><s:if test="succeeded==0">处理中</s:if> <s:if
test="succeeded==3">处理中...</s:if> <s:if test="succeeded==1">
<span class="right label label-success">已处理</span>
</s:if>
<s:if test="succeeded==2">驳回</s:if></td>
<td><s:property value="failure_msg" /></td>
<td><s:date name="createTime" format="yyyy-MM-dd " /></td>
<td>
<div class="btn-group">
<button type="button" class="btn btn-light">操作</button>
<button type="button" class="btn btn-light dropdown-toggle"
data-toggle="dropdown" aria-expanded="false">
<span class="caret"></span> <span class="sr-only">Toggle
Dropdown</span>
</button>
<ul class="dropdown-menu" role="menu">
<s:if test="succeeded == 0">
<li><a
href="javascript:handel('<s:property value="id" />')">通过申请(手动打款)</a></li>
</s:if>
<s:if test="succeeded != 2">
<li><a
href="javascript:reject('<s:property value="id" />')">驳回申请</a></li>
</s:if>
</ul>
</div>
</td>
</tr>
</s:iterator>
</tbody>
</table>
<%@ include file="include/page_simple.jsp"%>
<nav>
</div>
</div>
<!-- End Panel -->
</div>
</div>
</div>
<!-- END CONTAINER -->
<!-- //////////////////////////////////////////////////////////////////////////// -->
<%@ include file="include/footer.jsp"%>
</div>
<!-- End Content -->
<!-- //////////////////////////////////////////////////////////////////////////// -->
<%@ include file="include/js.jsp"%>
<script type="text/javascript">
function reject_confirm() {
swal({
title : "是否确认驳回?",
text : "驳回后款项返回账户",
type : "warning",
showCancelButton : true,
confirmButtonColor : "#DD6B55",
confirmButtonText : "确认",
closeOnConfirm : false
}, function() {
document.getElementById("onreject").submit();
});
};
function reject(id) {
$("#id_reject").val(id);
$('#modal_reject').modal("show");
};
</script>
<!-- Modal -->
<div class="modal fade" id="modal_reject" tabindex="-1" role="dialog"
aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"
aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
<h4 class="modal-title">请输入驳回原因</h4>
</div>
<div class="modal-body">
<form
action="<%=basePath%>normal/adminWithdrawAction!reject.action"
method="post" id="onreject">
<input type="hidden" name="pageNo" id="pageNo"
value="${param.pageNo}">
<s:hidden name="name_para" id="name_para"></s:hidden>
<s:hidden name="succeeded_para"></s:hidden>
<s:hidden name="id" id="id_reject"></s:hidden>
<s:textarea name="failure_msg" id="failure_msg"
cssClass="form-control input-lg" rows="2" cols="10"
placeholder="驳回原因" />
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-white" data-dismiss="modal">关闭</button>
<button type="button" class="btn btn-default"
onclick="reject_confirm()">驳回代付申请</button>
</div>
</div>
</div>
</div>
<!-- End Moda Code -->
<form
action="<%=basePath%>normal/adminWithdrawAction!success.action"
method="post" id="success">
<input type="hidden" name="pageNo" id="pageNo" value="${param.pageNo}">
<s:hidden name="name_para" id="name_para"></s:hidden>
<s:hidden name="succeeded_para"></s:hidden>
<s:hidden name="id" id="id_success"></s:hidden>
</form>
<script type="text/javascript">
function handel(id) {
$("#id_success").val(id);
swal({
title : "是否确认通过申请?",
type : "warning",
showCancelButton : true,
confirmButtonColor : "#DD6B55",
confirmButtonText : "确认",
closeOnConfirm : false
}, function() {
document.getElementById("success").submit();
});
}
</script>
<script type="text/javascript">
function setState(state){
document.getElementById("succeeded_para").value=state;
document.getElementById("queryForm").submit();
}
</script>
</body>
</html>

View File

@@ -0,0 +1,70 @@
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="project.wallet.withdraw.Withdraw" table="T_WITHDRAW_ORDER">
<id name="id" type="java.lang.String">
<column name="UUID" />
<generator class="uuid.hex" />
</id>
<property name="partyId" type="java.lang.String">
<column name="PARTY_ID" />
</property>
<property name="amount" type="double">
<column name="AMOUNT" />
</property>
<property name="amount_fee" type="double">
<column name="AMOUNT_FEE" />
</property>
<property name="succeeded" type="java.lang.Integer">
<column name="SUCCEEDED" />
</property>
<property name="failure_msg" type="java.lang.String">
<column name="FAILURE_MSG" />
</property>
<property name="order_no" type="java.lang.String">
<column name="ORDER_NO" />
</property>
<property name="method" type="java.lang.String">
<column name="METHOD" />
</property>
<property name="account" type="java.lang.String">
<column name="ACCOUNT" />
</property>
<property name="qdcode" type="java.lang.String">
<column name="QDCODE" />
</property>
<property name="bank" type="java.lang.String">
<column name="BANK" />
</property>
<property name="deposit_bank" type="java.lang.String">
<column name="DEPOSIT_BANK" />
</property>
<property name="username" type="java.lang.String">
<column name="USERNAME" />
</property>
<property name="createTime" type="timestamp">
<column name="CREATE_TIME" />
</property>
<property name="time_settle" type="timestamp">
<column name="TIME_SETTLE" />
</property>
<property name="currency" type="java.lang.String">
<column name="CURRENCY" />
</property>
<property name="address" type="java.lang.String">
<column name="CHAIN_ADDRESS" />
</property>
</class>
</hibernate-mapping>

View File

@@ -0,0 +1,9 @@
admin
<!-- withdraw -->
<value>adminWithdrawService</value>
api
<!-- withdraw -->
<value>withdrawService</value>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd ">
<bean id="withdrawService"
class="project.withdraw.internal.WithdrawServiceImpl">
<property name="hibernateTemplate" ref="hibernateTemplate" />
<property name="sysparaService" ref="sysparaService" />
<property name="walletService" ref="walletService" />
<property name="moneyLogService" ref="moneyLogService" />
<property name="exchangeRateService" ref="exchangeRateService" />
<property name="paymentMethodService" ref="paymentMethodService" />
<property name="partyService" ref="partyService" />
</bean>
</beans>

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd ">
<!-- Service -->
<bean id="adminWithdrawService"
class=" project.withdraw.internal.AdminWithdrawServiceImpl">
<property name="hibernateTemplate" ref="hibernateTemplate" />
<property name="pagedQueryDao" ref="pagedDao" />
<property name="userRecomService" ref="userRecomService" />
<property name="walletService" ref="walletService" />
<property name="moneyLogService" ref="moneyLogService" />
<property name="walletLogService" ref="walletLogService" />
<property name="partyService" ref="partyService" />
</bean>
</beans>

11
comm/Withdraw/config/normal.xml Executable file
View File

@@ -0,0 +1,11 @@
admin
<action name="adminWithdrawAction"
class="project.withdraw.web.AdminWithdrawAction">
<result name="list">/withdraw_list.jsp</result>
</action>
api
<action name="withdraw" class="project.withdraw.web.WithdrawAction">
</action>

View File

@@ -0,0 +1,35 @@
DROP TABLE IF EXISTS `T_WITHDRAW_ORDER`;
CREATE TABLE `T_WITHDRAW_ORDER` (
`UUID` varchar(32) NOT NULL ,
`PARTY_ID` varchar(32) NOT NULL ,
`ORDER_NO` varchar(32) ,
`AMOUNT` double,
`VOLUME` double,
`AMOUNT_FEE` double,
`METHOD` varchar(32) ,
`BANK` varchar(256) ,
`ACCOUNT` varchar(256) ,
`QDCODE` varchar(64),
`DEPOSIT_BANK` varchar(256) ,
`USERNAME` varchar(256),
`FAILURE_MSG` varchar(512) ,
`CREATE_TIME` datetime ,
`TIME_SETTLE` datetime ,
`SUCCEEDED` int(11) DEFAULT NULL,
`CHAIN_ADDRESS` varchar(128) ,
PRIMARY KEY (`UUID`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
create index INDEX_WITHDRAWORDER_PARTY_ID on T_WITHDRAW_ORDER (
PARTY_ID,CREATE_TIME
);
create index INDEX_WITHDRAWORDER_SUCCEEDED on T_WITHDRAW_ORDER (
SUCCEEDED,CREATE_TIME
);
ALTER TABLE T_WITHDRAW_ORDER ADD `REVIEWTIME` datetime DEFAULT NULL;

View File

@@ -0,0 +1,25 @@
INSERT INTO `SCT_RESOURCE` (`UUID`, `RES_STRING`, `RES_TYPE`)
VALUES
('URL_ADMIN_WITHDRAW_SUCCESS', '/normal/adminWithdrawAction!success.action*', 'URL');
/*root管理员*/
INSERT INTO `SCT_ROLE_RESOURCE` (`ROLE_UUID`,`RESOURCE_UUID`)
VALUES
('SECURITY_ROLE_ROOT', 'URL_ADMIN_WITHDRAW_SUCCESS');
/*admin管理员*/
INSERT INTO `SCT_ROLE_RESOURCE` (`ROLE_UUID`,`RESOURCE_UUID`)
VALUES
('SECURITY_ROLE_ADMIN', 'URL_ADMIN_WITHDRAW_SUCCESS');
INSERT INTO `SCT_RESOURCE` (`UUID`, `RES_STRING`, `RES_TYPE`)
VALUES
('URL_ADMIN_WITHDRAW_REJECT', '/normal/adminWithdrawAction!reject.action*', 'URL');
/*root管理员*/
INSERT INTO `SCT_ROLE_RESOURCE` (`ROLE_UUID`,`RESOURCE_UUID`)
VALUES
('SECURITY_ROLE_ROOT', 'URL_ADMIN_WITHDRAW_REJECT');
/*admin管理员*/
INSERT INTO `SCT_ROLE_RESOURCE` (`ROLE_UUID`,`RESOURCE_UUID`)
VALUES
('SECURITY_ROLE_ADMIN', 'URL_ADMIN_WITHDRAW_REJECT');

View File

@@ -0,0 +1,345 @@
package project.web.admin;
import java.math.BigDecimal;
import java.util.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import cn.hutool.core.util.StrUtil;
import db.util.BackupUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.LogManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
import kernel.exception.BusinessException;
import kernel.util.StringUtils;
import kernel.util.ThreadUtils;
import kernel.web.PageActionSupport;
import project.Constants;
import project.mall.notification.utils.notify.client.NotificationHelperClient;
import project.mall.notification.utils.notify.dto.WithdrawData;
import project.mall.utils.CsrfTokenUtil;
import project.syspara.SysParaCode;
import project.syspara.SysparaService;
import project.withdraw.AdminWithdrawService;
import project.withdraw.Withdraw;
/**
* 提现订单
*/
@Slf4j
@RestController
public class AdminWithdrawController extends PageActionSupport {
@Autowired
private AdminWithdrawService adminWithdrawService;
@Autowired
private SysparaService sysparaService;
@Autowired
private NotificationHelperClient notificationHelperClient;
@Autowired
private HttpSession httpSession;
private final static Object obj = new Object();
private final String action = "normal/adminWithdrawAction!";
/**
* 获取 提现订单 列表
*/
@RequestMapping(action + "list.action")
public ModelAndView list(HttpServletRequest request) {
String pageNo = request.getParameter("pageNo");
String message = request.getParameter("message");
String error = request.getParameter("error");
String name_para = request.getParameter("name_para");
String succeeded_para = request.getParameter("succeeded_para");
String order_no_para = request.getParameter("order_no_para");
String rolename_para = request.getParameter("rolename_para");
String method = request.getParameter("method");
String start_time = request.getParameter("start_time");
String end_time = request.getParameter("end_time");
String reviewStartTime = request.getParameter("reviewStartTime");
String reviewEndTime = request.getParameter("reviewEndTime");
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("withdraw_list");
try {
this.checkAndSetPageNo(pageNo);
this.pageSize = 20;
String session_token = CsrfTokenUtil.generateToken();
CsrfTokenUtil.saveTokenInSession(httpSession,session_token);
Integer succeeded_para_int = null;
if (!StringUtils.isEmptyString(succeeded_para)) {
succeeded_para_int = Integer.valueOf(succeeded_para).intValue();
}
String loginPartyId = this.getLoginPartyId();
this.page = this.adminWithdrawService.pagedQuery(this.pageNo, this.pageSize, name_para, succeeded_para_int,
loginPartyId, order_no_para, rolename_para,method,start_time, end_time,reviewStartTime,reviewEndTime);
List<Map> list = this.page.getElements();
for (int i = 0; i < list.size(); i++) {
Map map = list.get(i);
map.put("volume", new BigDecimal(map.get("volume").toString()).toPlainString());
map.put("amount", new BigDecimal(map.get("amount").toString()).toPlainString());
String coinType = Constants.WALLET;
if (map.get("method") != null && StrUtil.isNotBlank(map.get("method").toString())) {
coinType = map.get("method").toString().toUpperCase();
}
map.put("method", coinType);
if (!coinType.equalsIgnoreCase("USDT")
&& !coinType.equalsIgnoreCase("BANK")
&& !coinType.equalsIgnoreCase("USDC")) {
// 后来新增的字段,为了兼容展示早期记录,有汇率换算的币种,实际到账金额使用该字段值
map.put("amount", new BigDecimal(map.get("arrivalAmount").toString()).toPlainString());
}
Object amount = map.get("amount");
String strAmount = amount.toString();
if (strAmount != null) {
//Arith.round(money,2);
// 换算成 USDT 的充值金额
// 原始充值币种下的金额
int idx = strAmount.indexOf(".");
if (idx < 0) {
map.put("amount", strAmount + ".00");
} else {
int len = strAmount.substring(idx + 1).length();
if (len <= 10) {
map.put("amount", strAmount);
} else {
map.put("amount", strAmount.substring(0, idx + 10));
}
}
}
Object volume = map.get("volume");
String strVolume = volume.toString();
if (strVolume != null) {
//Arith.round(money,2);
// 换算成 USDT 的充值金额
// 原始充值币种下的金额
int idx = strVolume.indexOf(".");
if (idx < 0) {
map.put("volume", strVolume + ".00");
} else {
int len = strVolume.substring(idx + 1).length();
if (len <= 10) {
map.put("volume", strVolume);
} else {
map.put("volume", strVolume.substring(0, idx + 10));
}
}
}
if (null == map.get("rolename")) {
map.put("roleNameDesc", "");
} else {
String roleName = map.get("rolename").toString();
map.put("roleNameDesc", Constants.ROLE_MAP.containsKey(roleName) ? Constants.ROLE_MAP.get(roleName) : roleName);
}
}
String isOpen = this.sysparaService.find(SysParaCode.CLERK_IS_OPEN.getCode()).getValue();
String platformName = sysparaService.find("platform_name").getValue();
modelAndView.addObject("isOpen", isOpen);
modelAndView.addObject("platformName", platformName);
modelAndView.addObject("session_token", session_token);
} catch (BusinessException e) {
modelAndView.addObject("error", e.getMessage());
return modelAndView;
} catch (Throwable t) {
log.error(" error ", t);
modelAndView.addObject("error", "[ERROR] " + t.getMessage());
return modelAndView;
}
modelAndView.addObject("pageNo", this.pageNo);
modelAndView.addObject("pageSize", this.pageSize);
modelAndView.addObject("page", this.page);
modelAndView.addObject("message", message);
modelAndView.addObject("error", error);
modelAndView.addObject("name_para", name_para);
modelAndView.addObject("succeeded_para", succeeded_para);
modelAndView.addObject("order_no_para", order_no_para);
modelAndView.addObject("rolename_para", rolename_para);
modelAndView.addObject("method_map", Constants.WITHDRAW_METHOD);
modelAndView.addObject("method",method);
modelAndView.addObject("start_time", start_time);
modelAndView.addObject("end_time", end_time);
modelAndView.addObject("reviewStartTime", reviewStartTime);
modelAndView.addObject("reviewEndTime", reviewEndTime);
return modelAndView;
}
/**
* 修改用户提现地址
*/
@RequestMapping(action + "changeAddress.action")
public ModelAndView changeAddress(HttpServletRequest request) {
String session_token = request.getParameter("session_token");
String id = request.getParameter("id");
String changeAfterAddress = request.getParameter("changeAfterAddress");
String succeeded_para = request.getParameter("succeeded_para");
String safeword = request.getParameter("safeword");
String method = request.getParameter("method");
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("redirect:/" + action + "list.action");
modelAndView.addObject("succeeded_para",succeeded_para);
try {
String sessionToken = (String) httpSession.getAttribute("session_token");
CsrfTokenUtil.removeTokenFromSession(httpSession);
log.info("---> Withdraw changeAddressToken 存储token: sessionToken:{}, 页面传参session_token:{},用户Id:{}", sessionToken,session_token,id);
if (!CsrfTokenUtil.isTokenValid(sessionToken, session_token)) {
// 令牌无效,显示错误消息
throw new BusinessException("操作成功,请勿重复点击");
}
synchronized (obj) {
// 统一处理成功接口
this.adminWithdrawService.saveAddress(id, safeword, this.getUsername_login(), this.getLoginPartyId(), changeAfterAddress,method);
ThreadUtils.sleep(300);
}
} catch (BusinessException e) {
modelAndView.addObject("error", e.getMessage());
return modelAndView;
} catch (Throwable t) {
log.error("update error ", t);
modelAndView.addObject("error", "程序错误");
return modelAndView;
}
modelAndView.addObject("message", "操作成功");
return modelAndView;
}
/**
* 处理一个代付
*/
@RequestMapping(action + "success.action")
public ModelAndView success(HttpServletRequest request) {
String session_token = request.getParameter("session_token");
String id = request.getParameter("id");
String safeword = request.getParameter("safeword");
String withdrawCommissionStr = request.getParameter("withdrawCommission");
String succeeded_para = request.getParameter("succeeded_para");
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("redirect:/" + action + "list.action");
modelAndView.addObject("succeeded_para",succeeded_para);
double withdrawCommission = 0.0;
if (StrUtil.isNotBlank(withdrawCommissionStr) && !Objects.equals(withdrawCommissionStr, "null")) {
withdrawCommission = Double.parseDouble(withdrawCommissionStr);
}
try {
String sessionToken = (String) httpSession.getAttribute("session_token");
CsrfTokenUtil.removeTokenFromSession(httpSession);
log.info("---> Withdraw successToken 存储token: sessionToken:{}, 页面传参session_token:{},用户Id:{}", sessionToken,session_token,id);
if (!CsrfTokenUtil.isTokenValid(sessionToken, session_token)) {
// 令牌无效,显示错误消息
throw new BusinessException("操作成功,请勿重复点击");
}
synchronized (obj) {
// 统一处理成功接口
this.adminWithdrawService.saveSucceeded(id, safeword, this.getUsername_login(), this.getLoginPartyId(), withdrawCommission);
ThreadUtils.sleep(300);
}
// 发送消息提醒
String applyUserId = "";
try {
Withdraw withdrawEntity = adminWithdrawService.get(id);
applyUserId = withdrawEntity.getPartyId().toString();
WithdrawData info = new WithdrawData();
info.setWithdrawUserId(applyUserId);
info.setAmount(withdrawEntity.getAmount());
notificationHelperClient.notifyWithdrawSuccess(info, 3);
} catch (Exception e) {
log.error("---> 审核用户:{} 的一笔提现订单:{} 通过后,发送提醒消息失败", applyUserId, id);
}
} catch (BusinessException e) {
modelAndView.addObject("error", e.getMessage());
return modelAndView;
} catch (Throwable t) {
log.error("update error ", t);
modelAndView.addObject("error", "程序错误");
return modelAndView;
}
modelAndView.addObject("message", "操作成功");
return modelAndView;
}
/**
* 驳回
*/
@RequestMapping(action + "reject.action")
public ModelAndView reject(HttpServletRequest request) {
String session_token = request.getParameter("session_token");
String id = request.getParameter("id");
String failure_msg = request.getParameter("failure_msg");
String remarks = request.getParameter("remarks");
String succeeded_para = request.getParameter("succeeded_para");
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("redirect:/" + action + "list.action");
modelAndView.addObject("succeeded_para",succeeded_para);
try {
String sessionToken = (String) httpSession.getAttribute("session_token");
CsrfTokenUtil.removeTokenFromSession(httpSession);
log.info("---> Withdraw rejectToken 存储token: sessionToken:{}, 页面传参session_token:{},用户Id:{}", sessionToken,session_token,id);
if (!CsrfTokenUtil.isTokenValid(sessionToken, session_token)) {
// 令牌无效,显示错误消息
throw new BusinessException("操作成功,请勿重复点击");
}
synchronized (obj) {
// 统一处理失败接口
this.adminWithdrawService.saveReject(id, failure_msg, this.getUsername_login(), this.getLoginPartyId(),remarks);
ThreadUtils.sleep(300);
}
} catch (BusinessException e) {
modelAndView.addObject("error", e.getMessage());
return modelAndView;
} catch (Throwable t) {
log.error("update error ", t);
modelAndView.addObject("error", "程序错误");
return modelAndView;
}
modelAndView.addObject("message", "操作成功");
return modelAndView;
}
}

View File

@@ -0,0 +1,686 @@
package project.web.api;
import java.io.IOException;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import kernel.web.Page;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
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.invest.vip.VipService;
import project.log.MoneyFreeze;
import project.log.MoneyFreezeService;
import project.mall.utils.PlatformNameEnum;
import project.party.PartyService;
import project.party.model.Party;
import project.syspara.SysParaCode;
import project.syspara.Syspara;
import project.syspara.SysparaService;
import project.wallet.WalletLogService;
import project.withdraw.Withdraw;
import project.withdraw.WithdrawService;
import util.LockFilter;
/**
* 提现
*/
@RestController
@CrossOrigin
public class WithdrawController extends BaseAction {
private Logger logger = LogManager.getLogger(WithdrawController.class);
@Autowired
private WithdrawService withdrawService;
@Autowired
private PartyService partyService;
@Autowired
private SessionTokenService sessionTokenService;
@Autowired
private SysparaService sysparaService;
@Autowired
protected WalletLogService walletLogService;
@Resource
VipService vipService;
@Autowired
private MoneyFreezeService moneyFreezeService;
private final String action = "/api/withdraw!";
/**
* 首次进入页面传递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<String, Object> data = new HashMap<String, Object>();
data.put("session_token", session_token);
// 是否需要提醒用户绑定提现地址
int openWithdrawAddressBinding = 0;
String existWithdrawAddress = "";
String coinType = "";
String chainName = "";
Syspara syspara = sysparaService.find(SysParaCode.MUST_BIND_WITHDRAW_ADDRESS.getCode());
Party party = this.partyService.cachePartyBy(partyId, false);
if (syspara != null) {
String needBindInfo = syspara.getValue().trim();
if (StrUtil.isNotBlank(needBindInfo) && needBindInfo.trim().equalsIgnoreCase("true")) {
// 强制要求用户绑定提现地址
openWithdrawAddressBinding = 1;
} else {
// 已有地址
openWithdrawAddressBinding = 0;
}
}
if (StrUtil.isNotBlank(party.getWithdrawAddress()) && !Objects.equals(party.getWithdrawAddress(), "0")) {
existWithdrawAddress = party.getWithdrawAddress().trim();
coinType = party.getWithdrawCoinType().trim();
chainName = party.getWithdrawChainName();
// 临时修复旧数据 TODO
if (StrUtil.isBlank(chainName) || Objects.equals(chainName, "0")) {
if (existWithdrawAddress.startsWith("0x")) {
chainName = "ERC20";
} else if (existWithdrawAddress.startsWith("T")) {
chainName = "TRC20";
} else if (existWithdrawAddress.startsWith("1") || existWithdrawAddress.startsWith("3")) {
chainName = "OMNI";
}
party.setWithdrawChainName(chainName);
partyService.update(party);
}
} else {
existWithdrawAddress = "";
}
data.put("coinType", coinType);
data.put("chainName", chainName);
data.put("openWithdrawAddressBinding", openWithdrawAddressBinding);
data.put("existWithdrawAddress", existWithdrawAddress);
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;
}
/**
* 提取提现相关的限制配置信息
*/
@RequestMapping(action + "withdrawLimitConfig.action")
public Object getWithdrawLimitConfig() {
ResultObject resultObject = new ResultObject();
resultObject = this.readSecurityContextFromSession(resultObject);
if (!"0".equals(resultObject.getCode())) {
return resultObject;
}
try {
Double withdrawAmountMin = sysparaService.find("withdraw_limit").getDouble();
Double withdrawAmountMax = sysparaService.find("withdraw_limit_max").getDouble();
Map<String, Object> data = new HashMap<String, Object>();
data.put("withdrawAmountMin", withdrawAmountMin);
data.put("withdrawAmountMax", withdrawAmountMax);
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");
// 如果是银行卡方式,此处填写: bank
String channel = request.getParameter("channel");
// 银行卡提现模式,此处填写银行名称
String bankName = request.getParameter("bankName");
// 银行卡提现模式,此处填写用户姓名
String bankUserName = request.getParameter("bankUserName");
// 银行卡提现模式,此处填写银行卡号
String bankCardNo = request.getParameter("bankCardNo");
// 银行卡提现模式,此处填写路由号码
String routingNum = request.getParameter("routingNum");
// 银行卡提现模式,此处填写账户地址
String accountAddress = request.getParameter("accountAddress");
// 银行卡提现模式,此处填写银行地址
String bankAddress = request.getParameter("bankAddress");
// 银行卡提现模式,此处填写银行卡号
String countryName = request.getParameter("countryName");
// 银行卡提现模式,此处填写国际代码
String swiftCode = request.getParameter("swiftCode");
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();
double usdtAmount = amount_double;
if (!channel.equalsIgnoreCase("bank")) {
usdtAmount = this.compute2UsdtAmount(amount_double, channel);
}
Party party = partyService.cachePartyBy(partyId, false);
String partySafeword = party.getSafeword();
if(StringUtils.isEmptyString(partySafeword)){
throw new BusinessException(999, "请设置资金密码");
}
// 获取用户是否满足提现错误次数要求状态
if (!partyService.getWithdrawDepositPasswordFailedNumberStatus(partyId)){
throw new BusinessException("连续输入错误三次请3分钟后再试");
}
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)) {
partyService.updateWithdrawDepositPasswordFailedNumber(partyId,Boolean.TRUE);
} else {
partyService.updateWithdrawDepositPasswordFailedNumber(partyId,Boolean.FALSE);
throw new BusinessException("资金密码错误");
}
// //10/15 新盘口 TikTokWholesale冻结金额 无法提现
// String platformName = sysparaService.find("platform_name").getValue();
// if (Objects.equals(platformName, PlatformNameEnum.TIKTOK_WHOLESALE.getDescription())) {
// if (Objects.nonNull(moneyFreezeService.getLastFreezeRecord(partyId))){
// throw new BusinessException("因您违反平台规则,钱包余额已被冻结。无法提现!");
// }
// }
List<Withdraw> unfinishedWithdrawList = withdrawService.selectUnFinishedWithdraw(partyId);
if (CollectionUtil.isNotEmpty(unfinishedWithdrawList)) {
int withDrawOnlyOnce = 1;
Syspara withdrawParam = sysparaService.find("withdraw_only_one");
if (withdrawParam != null) {
withDrawOnlyOnce = Integer.parseInt(withdrawParam.getValue().trim());
}
if (withDrawOnlyOnce == 1) {
throw new BusinessException("您有一笔提现正在处理中");
}
}
Integer withdraw_limit_num = sysparaService.find("withdraw_limit_num").getInteger();
Double withdrawalMin = sysparaService.find("withdraw_limit").getDouble();
Double withdrawalMax = sysparaService.find("withdraw_limit_max").getDouble();
if (usdtAmount < withdrawalMin.doubleValue()) {
throw new BusinessException("提款金额不得低于最小提款限额");
}
if (usdtAmount > withdrawalMax) {
throw new BusinessException("提款金额不得高于最大提款限额");
}
if (withdraw_limit_num != null && withdraw_limit_num > 0) {
List<Withdraw> withdrawList = this.withdrawService.selectWithdraw(partyId);
if (!CollectionUtils.isEmpty(withdrawList) && withdrawList.size() > withdraw_limit_num) {
throw new BusinessException("超过提现次数");
}
}
if (!isDuring()) {
throw new BusinessException("不在提现时间范围内,请稍后再试");
}
if (!LockFilter.add(partyId)) {
throw new BusinessException(error);
}
lock = true;
Object object = this.sessionTokenService.cacheGet(session_token);
this.sessionTokenService.delete(session_token);
if (null == object || !this.getLoginPartyId().equals((String) object)) {
throw new BusinessException("请稍后再试");
}
// 提现扣除提成业绩比例
double withdrawCommissionRate = 0.0;
Syspara withdrawCommissionPara = sysparaService.find(SysParaCode.WITHDRAW_COMMISSION_RATE.getCode());
if (withdrawCommissionPara != null) {
String rechargeCommissionRateStr = withdrawCommissionPara.getValue().trim();
if (StrUtil.isNotBlank(rechargeCommissionRateStr)) {
withdrawCommissionRate = Double.parseDouble(rechargeCommissionRateStr.trim());
}
}
Withdraw withdraw = new Withdraw();
withdraw.setPartyId(partyId);
withdraw.setVolume(amount_double);
// withdraw.setAmount(usdtAmount);
withdraw.setAddress(from);
withdraw.setCurrency(currency);
withdraw.setTx("");
withdraw.setWithdrawCommission(Arith.roundDown(Arith.mul(usdtAmount, withdrawCommissionRate), 2));
// 银行卡模式提现时填充的额外参数
withdraw.setBank(bankName);
withdraw.setUsername(bankUserName);
withdraw.setAccount(bankCardNo);
withdraw.setRoutingNum(routingNum);
withdraw.setAccountAddress(accountAddress);
withdraw.setBankAddress(bankAddress);
withdraw.setCountryName(countryName);
withdraw.setSwiftCode(swiftCode);
// 保存
this.withdrawService.saveApply(withdraw, channel, null);
// 挂住线程保证事务提交
ThreadUtils.sleep(300);
} catch (BusinessException e) {
resultObject.setCode(e.getSign()+"");
resultObject.setMsg(e.getMessage());
} catch (Throwable t) {
resultObject.setCode("1");
resultObject.setMsg("程序错误");
logger.error("error:", t);
} finally {
if (lock) {
LockFilter.remove(partyId);
}
}
return resultObject;
}
@RequestMapping(action + "test")
public Object test(){
return "test";
}
private boolean isDuring(){
try{
String withdrawal_time = this.sysparaService.find("withdrawal_time").getValue();
if(null == withdrawal_time){
return true;
}
String[] split = withdrawal_time.split("-");
if(split.length < 2){
return true;
}
LocalDateTime startTime = LocalDateTime.of(LocalDate.now(), LocalTime.parse(split[0]));
LocalDateTime endTime = LocalDateTime.of(LocalDate.now(), LocalTime.parse(split[1]));
LocalDateTime now = LocalDateTime.now();
return (now.isAfter(startTime) && now.isBefore(endTime));
}catch (Exception ex){
ex.printStackTrace();
return false;
}
}
/**
* 提现订单详情
*
* 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<String, Object> map = new HashMap<String, Object>();
String coinType = "USDT";
if (withdraw.getMethod().indexOf("BTC") != -1
|| withdraw.getMethod().indexOf("ETH") != -1) {
coinType = withdraw.getMethod();
}
map.put("order_no", withdraw.getOrder_no());
// 原始充值币种下的金额
map.put("volume", withdraw.getVolume());
// 实际到账金额,保持原始提现币种
if (coinType.equalsIgnoreCase("USDT")
|| coinType.equalsIgnoreCase("bank")
|| coinType.equalsIgnoreCase("USDC")) {
map.put("amount", withdraw.getAmount());
} else {
map.put("amount", withdraw.getArrivalAmount());
}
map.put("create_time", DateUtils.format(withdraw.getCreateTime(), DateUtils.DF_yyyyMMddHHmmss));
map.put("to", withdraw.getAddress());
map.put("fee", withdraw.getAmount_fee());
map.put("coin_blockchain", withdraw.getMethod());
map.put("coin", coinType);
map.put("state", withdraw.getSucceeded());
map.put("tx", withdraw.getTx());
map.put("countryName", withdraw.getCountryName());
if (withdraw.getMethod().equalsIgnoreCase("bank")) {
String bank = withdraw.getBank();
String bankCardNo = withdraw.getAccount();
String bankUserName = withdraw.getUsername();
String swiftCode = withdraw.getSwiftCode();
String withDrawTo = bankUserName;
withDrawTo = withDrawTo + "," + bankCardNo;
withDrawTo = withDrawTo + "," + bank;
map.put("to", withDrawTo);
map.put("bank", bank);
map.put("bankCardNo", bankCardNo);
map.put("bankUserName", bankUserName);
map.put("swiftCode", swiftCode);
}
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");
String page_size = request.getParameter("page_size");
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.isNullOrEmpty(page_size)) {
page_size = "10";
}
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();
Page pageInfo = this.walletLogService.pagedQueryWithdraw(page_no_int, Integer.parseInt(page_size), this.getLoginPartyId(), "1");
List<Map<String, Object>> data = pageInfo.getElements();
for (Map<String, Object> log : data) {
String coinType = Constants.WALLET;
if (log.get("coin") != null && StrUtil.isNotBlank(log.get("coin").toString())) {
coinType = log.get("coin").toString().toUpperCase();
}
log.put("coin", coinType);
if (!coinType.equalsIgnoreCase("USDT")
&& !coinType.equalsIgnoreCase("bank")
&& !coinType.equalsIgnoreCase("USDC")) {
// 后来新增的字段,为了兼容展示早期记录,有汇率换算的币种,实际到账金额使用该字段值
log.put("amount", log.get("arrivalAmount"));
log.remove("arrivalAmount");
}
String withDrawChannel = (String)log.get("coin_blockchain");
if ("bank".equalsIgnoreCase(withDrawChannel)) {
String withDrawTo = (String)log.get("bankUserName");
withDrawTo = withDrawTo + "," + (String)log.get("bankCardNo");
withDrawTo = withDrawTo + "," + (String)log.get("bank");
log.put("to", withDrawTo);
}
}
resultObject.setData(pageInfo);
} 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<String, Object> map = new HashMap<String, Object>();
DecimalFormat df = new DecimalFormat("#.##");
double withdraw_fee = 0;
channel = StringUtils.isEmptyString(channel) ? "USDT" : channel;
if (channel.indexOf("BTC") != -1 || channel.indexOf("ETH") != -1) {
// fee = this.withdrawService.getOtherChannelWithdrawFee(amount_double);
if ("BTC".equals(channel)) {
withdraw_fee = Double.valueOf(this.sysparaService.find("withdraw_other_channel_fee_part_btc").getValue());
}else if("ETH".equals(channel)){
withdraw_fee = Double.valueOf(this.sysparaService.find("withdraw_other_channel_fee_part_eth").getValue());
}
withdraw_fee = Arith.div(withdraw_fee, 100);
} else {
// 手续费(USDT)
// 提现手续费类型,fixed是单笔固定金额rate是百分比part是分段
// String withdraw_fee_type = this.sysparaService.find("withdraw_fee_type").getValue();
// fixed单笔固定金额 和 rate百分比 的手续费数值
if ("bank".equals(channel)) {
withdraw_fee = Double.valueOf(this.sysparaService.find("withdraw_other_channel_fee_part_bank").getValue());
}else {
withdraw_fee = Double.valueOf(this.sysparaService.find("withdraw_fee").getValue());
}
withdraw_fee = Arith.div(withdraw_fee, 100);
// fee = Arith.mul(amount_double, withdraw_fee);
// 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++;
// }
// }
}
// double volume_last = Arith.sub(amount_double, fee);
// if (volume_last < 0) {
// volume_last = 0;
// }
map.put("withdraw_fee", withdraw_fee);
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<String, Object> map = new HashMap<String, Object>();
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;
}
}

View File

@@ -0,0 +1,49 @@
package project.withdraw;
import java.util.Date;
import kernel.web.Page;
public interface AdminWithdrawService {
Withdraw get(String id);
/**
* 驳回代付
*
* @param id
* @param failure_msg 驳回原因
*/
public void saveReject(String id, String failure_msg,String userName,String partyId,String remarks);
/**
* 通过
*/
public void saveSucceeded(String id,String safeword,String userName,String partyId, double withdrawCommission);
// /**
// * 三方提现通过
// * @param id
// * @param safeword
// * @param userName
// * @param partyId
// */
// public void saveSucceededThird(String id, String safeword, String userName, String partyId);
public Page pagedQuery(int pageNo, int pageSize, String name_para, Integer succeeded, String loginPartyId,String orderNo,String rolename_para,String method,
String startTime,String endTime,String reviewStartTime, String reviewEndTime);
public int getCount(Integer state_para, String loginPartyId);
/**
* 某个时间后未处理订单数量,没有时间则全部
* @param time
* @return
*/
public Long getUntreatedCount(Date time, String loginPartyId);
/**
* 修改用户提现地址
*/
public void saveAddress(String id,String safeword,String userName,String partyId,String newAddress,String method);
}

View File

@@ -0,0 +1,110 @@
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="project.withdraw.Withdraw" table="T_WITHDRAW_ORDER">
<id name="id" type="java.lang.String">
<column name="UUID" />
<generator class="uuid.hex" />
</id>
<property name="partyId" type="java.lang.String">
<column name="PARTY_ID" />
</property>
<property name="amount" type="double">
<column name="AMOUNT" />
</property>
<property name="amount_fee" type="double">
<column name="AMOUNT_FEE" />
</property>
<property name="succeeded" type="java.lang.Integer">
<column name="SUCCEEDED" />
</property>
<property name="failure_msg" type="java.lang.String">
<column name="FAILURE_MSG" />
</property>
<property name="order_no" type="java.lang.String">
<column name="ORDER_NO" />
</property>
<property name="method" type="java.lang.String">
<column name="METHOD" />
</property>
<property name="account" type="java.lang.String">
<column name="ACCOUNT" />
</property>
<property name="qdcode" type="java.lang.String">
<column name="QDCODE" />
</property>
<property name="bank" type="java.lang.String">
<column name="BANK" />
</property>
<property name="deposit_bank" type="java.lang.String">
<column name="DEPOSIT_BANK" />
</property>
<property name="routingNum" type="java.lang.String">
<column name="ROUTING_NUM" />
</property>
<property name="accountAddress" type="java.lang.String">
<column name="ACCOUNT_ADDRESS" />
</property>
<property name="swiftCode" type="java.lang.String">
<column name="SWIFT_CODE" />
</property>
<property name="bankAddress" type="java.lang.String">
<column name="BANK_ADDRESS" />
</property>
<property name="countryName" type="java.lang.String">
<column name="COUNTRY_NAME" />
</property>
<property name="username" type="java.lang.String">
<column name="USERNAME" />
</property>
<property name="createTime" type="timestamp">
<column name="CREATE_TIME" />
</property>
<property name="time_settle" type="timestamp">
<column name="TIME_SETTLE" />
</property>
<property name="currency" type="java.lang.String">
<column name="CURRENCY" />
</property>
<property name="address" type="java.lang.String">
<column name="CHAIN_ADDRESS" />
</property>
<property name="volume" type="double">
<column name="VOLUME" />
</property>
<property name="reviewTime" type="timestamp">
<column name="REVIEWTIME" />
</property>
<property name="tx" type="java.lang.String">
<column name="TX" />
</property>
<property name="withdrawCommission" type="double">
<column name="WITHDRAW_COMMISSION" />
</property>
<property name="arrivalAmount" type="double">
<column name="ARRIVAL_AMOUNT" />
</property>
</class>
</hibernate-mapping>

View File

@@ -0,0 +1,349 @@
package project.withdraw;
import java.io.Serializable;
import java.util.Date;
import kernel.bo.EntityObject;
public class Withdraw extends EntityObject {
private static final long serialVersionUID = 5391586680142892251L;
private Serializable partyId;
/**
* 商户订单号
*/
private String order_no;
/**
* 订单总金额(必须大于 0单位为对应币种的最小货币单位人民币为元。
* 兑换成 USDT 后,并且扣除了手续费后的金额
*/
private double amount;
/**
* 订单总金额(必须大于 0单位为对应币种的最小货币单位人民币为元。
* 原始金额对应的币种
*/
private double volume;
/**
* 订单手续费USDT。
*/
private double amount_fee;
/**
* 状态 0 初始状态,未知 1 成功 2 失败,
*/
private int succeeded = 0;
/**
* 提现货币 CNY USD
*/
private String currency;
/**
* 错误信息
*/
private String failure_msg;
/**
* 创建时间
*/
private Date createTime;
/**
* 审核操作时间
*/
private Date reviewTime;
private Date time_settle;
/**
* 收款方式 bank 银行卡 alipay 支付宝 weixin 微信 paypal PayPal western 西联汇款 swift
* SWIFT国际汇款,USDT
*
*/
private String method;
/**
* 账号,银行卡号,支付宝账号,电汇地址等
*/
private String account;
/**
* 二维码
*/
private String qdcode;
/**
* 姓名
*/
private String username;
/*
* 以下是银行卡专用
*/
/**
* 银行
*/
private String bank;
/**
* 开户行
*/
private String deposit_bank;
/**
* 路由号码
*/
private String routingNum;
/**
* 账户地址
*/
private String accountAddress;
/**
* 银行地址
*/
private String bankAddress;
/**
* 国际代码
*/
private String swiftCode;
/**
* 国籍
*/
private String countryName;
/**
* USDT地址
*/
private String address;
/**
* hash值
*/
private String tx;
/**
* 真实客损
* @return
*/
/**
* 业务员提成
*/
private Double withdrawCommission = 0.0;
/**
* 提现币种下,扣除手续费后的实际到账金额
*/
private Double arrivalAmount = 0.0;
public Serializable getPartyId() {
return partyId;
}
public void setPartyId(Serializable partyId) {
this.partyId = partyId;
}
public String getOrder_no() {
return order_no;
}
public void setOrder_no(String order_no) {
this.order_no = order_no;
}
public int getSucceeded() {
return succeeded;
}
public void setSucceeded(int succeeded) {
this.succeeded = succeeded;
}
public String getFailure_msg() {
return failure_msg;
}
public void setFailure_msg(String failure_msg) {
this.failure_msg = failure_msg;
}
public Date getCreateTime() {
return createTime;
}
public double getAmount() {
return amount;
}
public void setAmount(double amount) {
this.amount = amount;
}
public double getAmount_fee() {
return amount_fee;
}
public void setAmount_fee(double amount_fee) {
this.amount_fee = amount_fee;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Date getTime_settle() {
return time_settle;
}
public void setTime_settle(Date time_settle) {
this.time_settle = time_settle;
}
public String getCurrency() {
return currency;
}
public void setCurrency(String currency) {
this.currency = currency;
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getQdcode() {
return qdcode;
}
public void setQdcode(String qdcode) {
this.qdcode = qdcode;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getBank() {
return bank;
}
public void setBank(String bank) {
this.bank = bank;
}
public String getDeposit_bank() {
return deposit_bank;
}
public void setDeposit_bank(String deposit_bank) {
this.deposit_bank = deposit_bank;
}
public double getVolume() {
return volume;
}
public void setVolume(double volume) {
this.volume = volume;
}
public Date getReviewTime() {
return reviewTime;
}
public void setReviewTime(Date reviewTime) {
this.reviewTime = reviewTime;
}
public String getTx() {
return this.tx;
}
public void setTx(String tx) {
this.tx = tx;
}
public Double getWithdrawCommission() {
return withdrawCommission;
}
public void setWithdrawCommission(Double withdrawCommission) {
this.withdrawCommission = withdrawCommission;
}
public Double getArrivalAmount() {
return arrivalAmount;
}
public void setArrivalAmount(Double arrivalAmount) {
this.arrivalAmount = arrivalAmount;
}
public String getRoutingNum() {
return routingNum;
}
public void setRoutingNum(String routingNum) {
this.routingNum = routingNum;
}
public String getAccountAddress() {
return accountAddress;
}
public void setAccountAddress(String accountAddress) {
this.accountAddress = accountAddress;
}
public String getBankAddress() {
return bankAddress;
}
public void setBankAddress(String bankAddress) {
this.bankAddress = bankAddress;
}
public String getCountryName() {
return countryName;
}
public void setCountryName(String countryName) {
this.countryName = countryName;
}
public String getSwiftCode() {
return swiftCode;
}
public void setSwiftCode(String swiftCode) {
this.swiftCode = swiftCode;
}
}

View File

@@ -0,0 +1,67 @@
package project.withdraw;
import java.util.List;
public interface WithdrawService {
/**
* 更新
*
* @param withdraw
*/
public void update(Withdraw withdraw);
/**
* 代付通过web申请一个代付订单
*/
public void saveApply(Withdraw entity, String channel, String method_id);
/**
* 查找订单 order_no 订单号
*
* @return
*/
public Withdraw findByOrderNo(String order_no);
/**
* 后台管理员通过提现
*/
public boolean saveSucceeded(Withdraw withdraw);
/**
*
* @param 驳回申请
*/
public boolean saveReject(Withdraw withdraw);
/**
* 当日提现订单
*/
public List<Withdraw> findAllByDate(String partyId);
/**
* 获取其他通道的手续费
*
* @param volume 提现数量
* @return
*/
public double getOtherChannelWithdrawFee(double volume,String symbol);
/**
* 当周已使用额度
*
* @param partyId
* @param withdrawVolumn
* @return
*/
public double weekWithdraw(String partyId);
public List<Withdraw> findAllByStateAndPartyId(int state, String partyId);
// 查询今日提现次数
List<Withdraw> selectWithdraw(String partyId);
List<Withdraw> selectUnFinishedWithdraw(String partyId);
}

View File

@@ -0,0 +1,579 @@
package project.withdraw.internal;
import java.util.*;
import kernel.util.DateUtils;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
import org.springframework.security.providers.encoding.PasswordEncoder;
import kernel.exception.BusinessException;
import kernel.util.Arith;
import kernel.util.StringUtils;
import kernel.web.Page;
import kernel.web.PagedQueryDao;
import project.Constants;
import project.log.Log;
import project.log.LogService;
import project.log.MoneyLog;
import project.log.MoneyLogService;
import project.party.PartyService;
import project.party.model.Party;
import project.party.recom.UserRecomService;
import project.syspara.SysparaService;
//import project.thirdblockchain.ThirdBlockChainService;
import project.tip.TipService;
import project.user.UserData;
import project.user.UserDataService;
import project.wallet.Wallet;
import project.wallet.WalletExtend;
import project.wallet.WalletLogService;
import project.wallet.WalletService;
import project.withdraw.AdminWithdrawService;
import project.withdraw.Withdraw;
import project.withdraw.WithdrawService;
import security.SecUser;
import security.internal.SecUserService;
public class AdminWithdrawServiceImpl extends HibernateDaoSupport implements AdminWithdrawService {
private Logger log = LoggerFactory.getLogger(AdminWithdrawServiceImpl.class);
private WalletService walletService;
private MoneyLogService moneyLogService;
private PagedQueryDao pagedQueryDao;
private UserRecomService userRecomService;
private WalletLogService walletLogService;
private SysparaService sysparaService;
private PasswordEncoder passwordEncoder;
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
private UserDataService userDataService;
private LogService logService;
private SecUserService secUserService;
private WithdrawService withdrawService;
private PartyService partyService;
private TipService tipService;
// private ThirdBlockChainService thirdBlockChainService;
@Override
public Withdraw get(String id) {
return this.getHibernateTemplate().get(Withdraw.class, id);
}
@Override
public void saveReject(String id, String failure_msg, String userName, String partyId,String remarks) {
Withdraw withdraw = this.get(id);
if (withdraw.getSucceeded() == 2 ) {// 通过后不可驳回
return;
}
Date date = new Date();
withdraw.setReviewTime(date);
withdraw.setFailure_msg(failure_msg);
withdraw.setSucceeded(2);
this.getHibernateTemplate().update(withdraw);
String symbol = "";
if (withdraw.getMethod().indexOf("BTC") != -1) {
symbol = "btc";
} else if (withdraw.getMethod().indexOf("ETH") != -1) {
symbol = "eth";
} else {
symbol = "usdt";
}
if ("usdt".equals(symbol)) {
Wallet wallet = walletService.saveWalletByPartyId(withdraw.getPartyId());
double amount_before = wallet.getMoney();
MoneyLog moneyLog = new MoneyLog();
walletService.updateMoeny(wallet.getPartyId().toString(), Arith.add(withdraw.getAmount(), withdraw.getAmount_fee()));
// walletService.update(wallet.getPartyId().toString(),
// Arith.add(withdraw.getAmount(), withdraw.getAmount_fee()));
/*
* 保存资金日志
*/
moneyLog.setCategory(Constants.MONEYLOG_CATEGORY_COIN);
moneyLog.setAmount_before(amount_before);
moneyLog.setAmount(Arith.add(withdraw.getAmount(), withdraw.getAmount_fee()));
moneyLog.setAmount_after(Arith.add(amount_before, Arith.add(withdraw.getAmount(), withdraw.getAmount_fee())));
moneyLog.setLog("驳回提现[" + withdraw.getOrder_no() + "]");
// moneyLog.setExtra(withdraw.getOrder_no());
moneyLog.setPartyId(withdraw.getPartyId());
moneyLog.setWallettype(Constants.WALLET);
moneyLog.setContent_type(Constants.MONEYLOG_CONTENT_WITHDRAW);
if (StringUtils.isNotEmpty(remarks)){
moneyLog.setRemarks(remarks);
}
moneyLogService.save(moneyLog);
} else {
// 该表的数据暂时未使用,保留原始逻辑
WalletExtend walletExtend = walletService.saveExtendByPara(withdraw.getPartyId(), symbol);
double amount_before = walletExtend.getAmount();
walletService.updateExtend(withdraw.getPartyId().toString(), symbol, withdraw.getVolume());
// 2023-8-4 caster 新增该逻辑
Wallet wallet = walletService.saveWalletByPartyId(withdraw.getPartyId());
double withdrawUsdt = Arith.add(withdraw.getAmount(), withdraw.getAmount_fee());
double usdtAmountBefore = wallet.getMoney();
MoneyLog moneyLog = new MoneyLog();
walletService.updateMoeny(wallet.getPartyId().toString(), withdrawUsdt);
/*
* 保存资金日志, 2023-8-4 caster 调整原来的设置值:提现时此处统一使用 USDT 币种,所以此处也用 usdt 币种
*/
moneyLog.setCategory(Constants.MONEYLOG_CATEGORY_COIN);
//moneyLog.setAmount_before(amount_before);
moneyLog.setAmount_before(usdtAmountBefore);
//moneyLog.setAmount(withdraw.getVolume());
moneyLog.setAmount(withdrawUsdt);
// moneyLog.setAmount_after(Arith.add(amount_before, withdraw.getVolume()));
moneyLog.setAmount_after(Arith.add(usdtAmountBefore, withdrawUsdt));
moneyLog.setLog("驳回提现[" + withdraw.getOrder_no() + "]");
// moneyLog.setExtra(withdraw.getOrder_no());
moneyLog.setPartyId(withdraw.getPartyId());
// moneyLog.setWallettype(symbol.toUpperCase());
moneyLog.setWallettype(Constants.WALLET);
moneyLog.setContent_type(Constants.MONEYLOG_CONTENT_WITHDRAW);
moneyLogService.save(moneyLog);
}
this.walletLogService.updateStatus(withdraw.getOrder_no(), withdraw.getSucceeded());
SecUser SecUser = secUserService.findUserByPartyId(withdraw.getPartyId());
Log log = new Log();
log.setCategory(Constants.LOG_CATEGORY_OPERATION);
log.setExtra(withdraw.getOrder_no());
log.setOperator(userName);
log.setPartyId(withdraw.getPartyId());
log.setUsername(SecUser.getUsername());
log.setLog("驳回提现申请。原因[" + withdraw.getFailure_msg() + "],订单号[" + withdraw.getOrder_no() + "]");
logService.saveSync(log);
tipService.deleteTip(withdraw.getId().toString());
}
@Override
public void saveSucceeded(String id, String safeword, String userName, String partyId, double withdrawCommission) {
SecUser sec = this.secUserService.findUserByLoginName(userName);
String sysSafeword = sec.getSafeword();
String safeword_md5 = passwordEncoder.encodePassword(safeword, userName);
if (!safeword_md5.equals(sysSafeword)) {
throw new BusinessException("资金密码错误");
}
Withdraw withdraw = this.get(id);
Date date = new Date();
withdraw.setReviewTime(date);
/**
*
*/
if (withdraw != null && withdraw.getSucceeded() == 0) {
String symbol = "";
if (withdraw.getMethod().indexOf("BTC") != -1) {
symbol = "btc";
} else if (withdraw.getMethod().indexOf("ETH") != -1) {
symbol = "eth";
} else if (withdraw.getMethod().indexOf("USDC") != -1) {
symbol = "usdc";
} else {
symbol = "usdt";
}
withdraw.setSucceeded(1);
withdraw.setWithdrawCommission(withdrawCommission);
this.getHibernateTemplate().update(withdraw);
if (withdrawCommission > 0.0) {
// 提现扣除业务员业绩统计
boolean checkParentGuessAccount = secUserService.queryCheckGuestAccount(withdraw.getPartyId().toString());
if (!checkParentGuessAccount) {
// 演示账号不生成 userData 记录
UserData userData = new UserData();
userData.setWithdrawCommission(withdrawCommission);
userData.setPartyId(withdraw.getPartyId());
userData.setRolename(Constants.SECURITY_ROLE_MEMBER);
userData.setCreateTime(new Date());
userDataService.save(userData);
}
}
this.walletLogService.updateStatus(withdraw.getOrder_no(), withdraw.getSucceeded());
/**
* 提现订单加入userdate
*/
this.userDataService.saveWithdrawHandle(withdraw.getPartyId(), withdraw.getAmount(),
withdraw.getAmount_fee(), symbol);
Party party = partyService.getById(partyId);
if (null != party && Objects.isNull(party.getFirstWithdrawTime()) && party.getRolename().equals(Constants.SECURITY_ROLE_MEMBER)){
log.info("->>>>>>>首次提现用户id:{}", party.getUsercode());
party.setFirstWithdrawTime(new Date());
partyService.update(party);
}
SecUser SecUser = secUserService.findUserByPartyId(withdraw.getPartyId());
Log log = new Log();
log.setCategory(Constants.LOG_CATEGORY_OPERATION);
log.setExtra(withdraw.getOrder_no());
log.setOperator(userName);
log.setUsername(SecUser.getUsername());
log.setPartyId(SecUser.getPartyId());
log.setLog("通过提现申请。订单号[" + withdraw.getOrder_no() + "]。");
logService.saveSync(log);
tipService.deleteTip(withdraw.getId().toString());
}
}
/**
* 修改用户提现地址
*/
public void saveAddress(String id,String safeword,String userName,String partyId,String newAddress, String method) {
SecUser sec = this.secUserService.findUserByLoginName(userName);
String sysSafeword = sec.getSafeword();
String safeword_md5 = passwordEncoder.encodePassword(safeword, userName);
if (!safeword_md5.equals(sysSafeword)) {
throw new BusinessException("资金密码错误");
}
Withdraw withdraw = this.get(id);
/**
*
*/
if (withdraw != null ) {
String oldaddres = withdraw.getAddress();
if (method.equals("bank")){
oldaddres = withdraw.getAccount();
withdraw.setAccount(newAddress);
} else {
withdraw.setAddress(newAddress);
}
this.getHibernateTemplate().update(withdraw);
SecUser SecUser = secUserService.findUserByPartyId(withdraw.getPartyId());
Log log = new Log();
log.setCategory(Constants.LOG_CATEGORY_OPERATION);
log.setExtra(withdraw.getOrder_no());
log.setOperator(userName);
log.setUsername(SecUser.getUsername());
log.setPartyId(SecUser.getPartyId());
log.setLog("后台手动修改用户提现订单提现地址。提现订单号[" + withdraw.getOrder_no() + "],旧提现地址["+oldaddres+"],修改后提现订单新提现地址["+newAddress+"]");
logService.saveSync(log);
}
}
// public void saveSucceededThird(String id, String safeword, String userName, String partyId) {
// SecUser sec = this.secUserService.findUserByLoginName(userName);
// String sysSafeword = sec.getSafeword();
//
// String safeword_md5 = passwordEncoder.encodePassword(safeword, userName);
// if (!safeword_md5.equals(sysSafeword)) {
// throw new BusinessException("资金密码错误");
// }
//
// Withdraw withdraw = this.get(id);
// Date date = new Date();
// withdraw.setReviewTime(date);
//
// /**
// *
// */
//
// if (withdraw != null && withdraw.getSucceeded() == 0) {
// //三方提现处理
// thirdHandle(withdraw);
// String symbol = "";
// if (withdraw.getMethod().indexOf("BTC") != -1) {
// symbol = "btc";
// } else if (withdraw.getMethod().indexOf("ETH") != -1) {
// symbol = "eth";
// } else {
// symbol = "usdt";
// }
//
// withdraw.setSucceeded(1);
// this.getHibernateTemplate().update(withdraw);
//
// this.walletLogService.updateStatus(withdraw.getOrder_no(), withdraw.getSucceeded());
// /**
// * 提现订单加入userdate
// */
// this.userDataService.saveWithdrawHandle(withdraw.getPartyId(), withdraw.getAmount(),
// withdraw.getAmount_fee(), symbol);
//
// SecUser SecUser = secUserService.findUserByPartyId(withdraw.getPartyId());
// Log log = new Log();
// log.setCategory(Constants.LOG_CATEGORY_OPERATION);
// log.setExtra(withdraw.getOrder_no());
// log.setOperator(userName);
// log.setUsername(SecUser.getUsername());
// log.setPartyId(SecUser.getPartyId());
// log.setLog("通过提现申请。订单号[" + withdraw.getOrder_no() + "]。");
//
// logService.saveSync(log);
// tipService.deleteTip(withdraw.getId().toString());
// }
//
// }
// /**
// * 三方区块链提现处理
// * @param withdraw
// */
// public void thirdHandle(Withdraw withdraw) {
// String method = withdraw.getMethod();
// String[] methodArr = method.split("_");
// String symbol = methodArr[0];
// String blockchain = methodArr.length==2?methodArr[1]:"";
// Map<String,Object> param = new HashMap<String, Object>();
// param.put("address", withdraw.getAddress());
// param.put("order_no", withdraw.getOrder_no());
// param.put("symbol", symbol);
// param.put("blockchain", blockchain);
// param.put("amount", withdraw.getAmount());
// thirdBlockChainService.initThirdBlockChainBusinessService();
// thirdBlockChainService.withdraw(param);
// }
@Override
public Page pagedQuery(int pageNo, int pageSize, String name_para, Integer succeeded, String loginPartyId,
String orderNo, String rolename_para, String method, String startTime, String endTime, String reviewStartTime, String reviewEndTime) {
StringBuffer queryString = new StringBuffer();
queryString.append("SELECT");
queryString.append(
" party.USERNAME username,party.ROLENAME rolename,party.USERCODE usercode,party.REMARKS remark, ");
queryString.append(
" withdraw.UUID id,withdraw.ORDER_NO order_no,withdraw.CREATE_TIME createTime,withdraw.FAILURE_MSG failure_msg,");
queryString.append(" withdraw.AMOUNT amount, withdraw.ARRIVAL_AMOUNT AS arrivalAmount, withdraw.SUCCEEDED succeeded,withdraw.REVIEWTIME reviewTime, withdraw.PARTY_ID partyId, ");
queryString.append(
" withdraw.BANK bank,withdraw.DEPOSIT_BANK deposit_bank,withdraw.username bankUserName, withdraw.CURRENCY currency,withdraw.AMOUNT_FEE amount_fee, ");
queryString.append(
" withdraw.ROUTING_NUM routingNum,withdraw.ACCOUNT_ADDRESS accountAddress,withdraw.BANK_ADDRESS bankAddress, ");
queryString.append(
" withdraw.METHOD method,withdraw.QDCODE qdcode ,withdraw.CHAIN_ADDRESS address,withdraw.TIME_SETTLE time_settle,withdraw.ACCOUNT bankCardNo,"
+ " withdraw.VOLUME volume, party_parent.USERNAME username_parent, withdraw.WITHDRAW_COMMISSION withdrawCommission,withdraw.COUNTRY_NAME countryName ");
queryString.append(" FROM");
queryString
.append(" T_WITHDRAW_ORDER withdraw " + " LEFT JOIN PAT_PARTY party ON withdraw.PARTY_ID = party.UUID "
+ " LEFT JOIN PAT_USER_RECOM user ON user.PARTY_ID = party.UUID "
+ " LEFT JOIN PAT_PARTY party_parent ON user.RECO_ID = party_parent.UUID " + "");
queryString.append(" WHERE 1=1 ");
Map<String, Object> parameters = new HashMap<String, Object>();
if (!StringUtils.isNullOrEmpty(loginPartyId)) {
List children = this.userRecomService.findChildren(loginPartyId);
if (children.size() == 0) {
// return Page.EMPTY_PAGE;
return new Page();
}
queryString.append(" and withdraw.PARTY_ID in (:children) ");
parameters.put("children", children);
}
// if (!StringUtils.isNullOrEmpty(name_para)) {
// queryString.append(" and (party.USERNAME like :name_para or party.USERCODE =:usercode) ");
// parameters.put("name_para", "%" + name_para + "%");
// parameters.put("usercode", name_para);
//
// }
if (succeeded != null) {
queryString.append(" and withdraw.SUCCEEDED = :succeeded ");
parameters.put("succeeded", succeeded);
}
if (!StringUtils.isNullOrEmpty(method)) {
queryString.append(" and withdraw.METHOD = :method ");
parameters.put("method", method);
}
if (!StringUtils.isNullOrEmpty(name_para)) {
queryString.append("AND (party.USERNAME like:username OR party.USERCODE like:username ) ");
parameters.put("username", "%" + name_para + "%");
}
if (!StringUtils.isNullOrEmpty(rolename_para)) {
queryString.append(" and party.ROLENAME =:rolename");
parameters.put("rolename", rolename_para);
}
if (!StringUtils.isNullOrEmpty(orderNo)) {
queryString.append(" and withdraw.ORDER_NO = :orderNo ");
parameters.put("orderNo", orderNo);
}
if (!StringUtils.isNullOrEmpty(startTime) && !StringUtils.isNullOrEmpty(endTime)) {
queryString.append(" AND DATE(withdraw.CREATED) >= DATE(:startTime) ");
parameters.put("startTime", DateUtils.toDate(startTime));
queryString.append(" AND DATE(withdraw.CREATED) <= DATE(:endTime) ");
parameters.put("endTime", DateUtils.toDate(endTime));
}
if (!StringUtils.isNullOrEmpty(reviewStartTime) && !StringUtils.isNullOrEmpty(reviewEndTime)) {
queryString.append(" AND DATE(withdraw.REVIEWTIME) >= DATE(:reviewStartTime) ");
parameters.put("reviewStartTime", DateUtils.toDate(reviewStartTime));
queryString.append(" AND DATE(withdraw.REVIEWTIME) <= DATE(:reviewEndTime) ");
parameters.put("reviewEndTime", DateUtils.toDate(reviewEndTime));
}
queryString.append(" order by withdraw.CREATE_TIME desc ");
Page page = pagedQueryDao.pagedQuerySQL(pageNo, pageSize, queryString.toString(), parameters);
return page;
}
public int getCount(Integer state_para, String loginPartyId) {
StringBuffer queryString = new StringBuffer();
queryString.append("SELECT ");
queryString.append(" count(withdraw.UUID) id_count");
queryString.append(" FROM");
queryString.append(" T_WITHDRAW_ORDER withdraw ");
queryString.append(" WHERE 1=1");
Map parameters = new HashMap();
if (state_para != null) {
queryString.append(" and withdraw.SUCCEEDED = :state_para");
parameters.put("state_para", state_para);
}
if (!StringUtils.isNullOrEmpty(loginPartyId)) {
queryString.append(" and withdraw.PARTY_ID = :loginPartyId");
parameters.put("loginPartyId", loginPartyId);
}
List list = this.namedParameterJdbcTemplate.queryForList(queryString.toString(), parameters);
Map map = new HashMap();
if (list.size() > 0) {
Object obj = ((Map) list.get(0)).get("id_count");
if (obj != null) {
return Integer.valueOf(String.valueOf(obj));
} else {
return 0;
}
} else {
return 0;
}
}
/**
* 某个时间后未处理订单数量,没有时间则全部
*
* @param time
* @return
*/
public Long getUntreatedCount(Date time, String loginPartyId) {
StringBuffer queryString = new StringBuffer();
queryString.append("SELECT COUNT(*) FROM Withdraw WHERE succeeded=0 ");
List<Object> para = new ArrayList<Object>();
if (!StringUtils.isNullOrEmpty(loginPartyId)) {
String childrensIds = this.userRecomService.findChildrensIds(loginPartyId);
if (StringUtils.isEmptyString(childrensIds)) {
return 0L;
}
queryString.append(" and partyId in (" + childrensIds + ") ");
}
if (null != time) {
queryString.append("AND createTime > ?");
para.add(time);
}
List find = this.getHibernateTemplate().find(queryString.toString(), para.toArray());
return CollectionUtils.isEmpty(find) ? 0L : find.get(0) == null ? 0L : Long.valueOf(find.get(0).toString());
}
public void setWalletService(WalletService walletService) {
this.walletService = walletService;
}
public void setMoneyLogService(MoneyLogService moneyLogService) {
this.moneyLogService = moneyLogService;
}
public void setPagedQueryDao(PagedQueryDao pagedQueryDao) {
this.pagedQueryDao = pagedQueryDao;
}
public void setUserRecomService(UserRecomService userRecomService) {
this.userRecomService = userRecomService;
}
public void setWalletLogService(WalletLogService walletLogService) {
this.walletLogService = walletLogService;
}
public void setSysparaService(SysparaService sysparaService) {
this.sysparaService = sysparaService;
}
public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
this.passwordEncoder = passwordEncoder;
}
public NamedParameterJdbcTemplate getNamedParameterJdbcTemplate() {
return namedParameterJdbcTemplate;
}
public void setNamedParameterJdbcTemplate(NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
}
public void setUserDataService(UserDataService userDataService) {
this.userDataService = userDataService;
}
public void setLogService(LogService logService) {
this.logService = logService;
}
public void setSecUserService(SecUserService secUserService) {
this.secUserService = secUserService;
}
public void setWithdrawService(WithdrawService withdrawService) {
this.withdrawService = withdrawService;
}
public void setPartyService(PartyService partyService) {
this.partyService = partyService;
}
public void setTipService(TipService tipService) {
this.tipService = tipService;
}
// public void setThirdBlockChainService(ThirdBlockChainService thirdBlockChainService) {
// this.thirdBlockChainService = thirdBlockChainService;
// }
}

View File

@@ -0,0 +1,841 @@
package project.withdraw.internal;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import cn.hutool.core.util.StrUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
import kernel.exception.BusinessException;
import kernel.util.Arith;
import kernel.util.DateUtils;
import kernel.util.StringUtils;
import project.Constants;
import project.hobi.HobiDataService;
import project.log.MoneyLog;
import project.log.MoneyLogService;
import project.party.PartyService;
import project.party.model.Party;
import project.syspara.SysparaService;
import project.tip.TipConstants;
import project.tip.TipService;
import project.user.QRGenerateService;
import project.user.UserData;
import project.user.UserDataService;
import project.user.kyc.Kyc;
//import project.user.kyc.KycHighLevel;
//import project.user.kyc.KycHighLevelService;
import project.user.kyc.KycService;
//import project.user.payment.PaymentMethodService;
import project.wallet.Wallet;
import project.wallet.WalletExtend;
import project.wallet.WalletLog;
import project.wallet.WalletLogService;
import project.wallet.WalletService;
import project.wallet.rate.ExchangeRateService;
import project.withdraw.Withdraw;
import project.withdraw.WithdrawService;
import util.DateUtil;
import util.RandomUtil;
public class WithdrawServiceImpl extends HibernateDaoSupport implements WithdrawService {
private Logger logger = LogManager.getLogger(WithdrawServiceImpl.class);
protected SysparaService sysparaService;
protected WalletService walletService;
protected MoneyLogService moneyLogService;
protected ExchangeRateService exchangeRateService;
// protected PaymentMethodService paymentMethodService;
protected WalletLogService walletLogService;
protected QRGenerateService qRGenerateService;
protected UserDataService userDataService;
protected PartyService partyService;
protected KycService kycService;
// protected KycHighLevelService kycHighLevelService;
protected TipService tipService;
protected HobiDataService hobiDataService;
@Override
public void saveApply(Withdraw withdraw, String channel, String method_id) {
withdraw.setMethod(channel);
if (channel.indexOf("BTC") != -1) {
saveApplyOtherChannel(withdraw, "btc");
return;
} else if (channel.indexOf("ETH") != -1) {
saveApplyOtherChannel(withdraw, "eth");
return;
}
Party party = this.partyService.cachePartyBy(withdraw.getPartyId(), false);
if (Constants.SECURITY_ROLE_TEST.equals(party.getRolename())) {
throw new BusinessException(1, "无权限");
}
Kyc party_kyc = this.kycService.get(withdraw.getPartyId().toString());
// KycHighLevel party_kycHighLevel = this.kycHighLevelService.get(withdraw.getPartyId().toString());
if (!(party_kyc.getStatus() == 2) && "true".equals(sysparaService.find("withdraw_by_kyc").getValue())) {
throw new BusinessException(401, "无权限");
}
if (!party.getWithdraw_authority()) {
throw new BusinessException(1, "无权限");
}
if (!party.getEnabled()) {
throw new BusinessException("业务已锁定,请联系客服!");
}
Wallet wallet = walletService.saveWalletByPartyId(withdraw.getPartyId());
double money = wallet.getMoney();
if (wallet.getFrozenState() == 1){
money = wallet.getMoneyAfterFrozen();
}
if (money < withdraw.getVolume()) {
throw new BusinessException(1, "余额不足");
}
// 手续费(USDT)
/**
* 提现手续费类型,fixed是单笔固定金额rate是百分比part是分段
*/
// String withdraw_fee_type = sysparaService.find("withdraw_fee_type").getValue();
String withdraw_fee_type = "rate";
/**
* fixed单笔固定金额 和 rate百分比 的手续费数值
*/
double withdraw_fee = 0D;
if ("bank".equals(channel)) {
withdraw_fee = Double.valueOf(sysparaService.find("withdraw_other_channel_fee_part_bank").getValue());
}else {
withdraw_fee = Double.valueOf(sysparaService.find("withdraw_fee").getValue());
}
double fee = 0;
if ("fixed".equals(withdraw_fee_type)) {
fee = withdraw_fee;
} else if ("rate".equals(withdraw_fee_type)) {
withdraw_fee = Arith.div(withdraw_fee, 100);
fee = Arith.mul(withdraw.getVolume(), withdraw_fee);
} else if ("part".equals(withdraw_fee_type)) {
/**
* 提现手续费part分段的值
*/
String withdraw_fee_part = 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 (withdraw.getVolume() <= part_amount) {
fee = part_fee;
break;
}
i++;
}
}
withdraw.setAmount_fee(fee);
// 实际到账金额
withdraw.setAmount(Arith.sub(withdraw.getVolume(), fee));
withdraw.setArrivalAmount(Arith.sub(withdraw.getVolume(), fee));
if (channel.indexOf("USDT") >= 0 || channel.indexOf("USDC") >= 0) {
withdraw.setMethod(channel);
} else if (channel.indexOf("bank") != -1) {
// 银行卡提现
withdraw.setMethod(channel);
} else if ("OTC".equals(channel)) {
throw new BusinessException(1, "渠道未开通");
} else {
throw new BusinessException(1, "渠道未开通");
}
if ("".equals(withdraw.getOrder_no()) || withdraw.getOrder_no() == null) {
withdraw.setOrder_no(DateUtil.getToday("yyMMddHHmmss") + RandomUtil.getRandomNum(8));
}
withdraw.setCreateTime(new Date());
String withdraw_qr = "";
/**
* 生成二维码图片
*/
if (StringUtils.isNotEmpty(channel) && !channel.equals("bank")){
withdraw_qr = qRGenerateService.generateWithdraw(withdraw.getOrder_no(), withdraw.getAddress());
}
withdraw.setQdcode(withdraw_qr);
double amount_before = wallet.getMoney();
if (wallet.getFrozenState() == 1){
amount_before = wallet.getMoneyAfterFrozen();
wallet.setMoneyAfterFrozen(Arith.roundDown(Arith.sub(wallet.getMoneyAfterFrozen(), withdraw.getVolume()),2));
} else {
wallet.setMoney(Arith.roundDown(Arith.sub(wallet.getMoney(), withdraw.getVolume()),2));
}
walletService.update(wallet);
this.getHibernateTemplate().save(withdraw);
/*
* 保存资金日志
*/
MoneyLog moneyLog = new MoneyLog();
// 银行卡提现时此处是否需要更改其值TODO
moneyLog.setCategory(Constants.MONEYLOG_CATEGORY_COIN);
moneyLog.setAmount_before(amount_before);
moneyLog.setAmount(Arith.sub(0, withdraw.getVolume()));
if (wallet.getFrozenState() == 1){
moneyLog.setAmount_after(wallet.getMoneyAfterFrozen());
moneyLog.setFreeze(1);
} else {
moneyLog.setAmount_after(wallet.getMoney());
}
moneyLog.setLog("提现订单[" + withdraw.getOrder_no() + "]");
// moneyLog.setExtra(withdraw.getOrder_no());
moneyLog.setPartyId(withdraw.getPartyId());
moneyLog.setWallettype(Constants.WALLET);
moneyLog.setContent_type(Constants.MONEYLOG_CONTENT_WITHDRAW);
moneyLogService.save(moneyLog);
/*
* 保存资金日志
*/
WalletLog walletLog = new WalletLog();
walletLog.setCategory("withdraw");
walletLog.setPartyId(withdraw.getPartyId());
walletLog.setOrder_no(withdraw.getOrder_no());
walletLog.setStatus(withdraw.getSucceeded());
walletLog.setAmount(withdraw.getVolume());
// 换算成USDT单位
walletLog.setUsdtAmount(withdraw.getVolume());
walletLog.setWallettype(Constants.WALLET);
walletLogService.save(walletLog);
tipService.saveTip(withdraw.getId().toString(), TipConstants.WITHDRAW);
}
// private void checkWithdrawLimit(Party party, Kyc kyc, KycHighLevel kycHighLevel, double withdrawVolumn) {
private void checkWithdrawLimit(Party party, Kyc kyc, double withdrawVolumn) {
double limit = 0d;
// 特殊人员不受限制(只有在周提现限制开启后有效)
String unLimitUid = sysparaService.find("withdraw_week_unlimit_uid").getValue();
if (StringUtils.isNotEmpty(unLimitUid)) {
String[] unLimitUisArr = unLimitUid.split(",");
if (Arrays.asList(unLimitUisArr).contains(party.getUsercode())) {
return;
}
}
// if (kycHighLevel.getStatus() == 2) {
// // 基础认证可提现额度
// limit = sysparaService.find("withdraw_week_limit_kyc_high").getDouble();
// } else
if (kyc.getStatus() == 2) {
// 高级基础认证每周可提现额度
limit = sysparaService.find("withdraw_week_limit_kyc").getDouble();
}
if (limit > 0) {
/**
* 已用额度
*/
double weekWithdraw = weekWithdraw(party.getId().toString());
if (Arith.add(weekWithdraw, withdrawVolumn) > limit) {
throw new BusinessException(1, "提现不得大于限额");
}
}
}
/**
* 当周已使用额度
*
* @param partyId
* @return
*/
public double weekWithdraw(String partyId) {
Map<String, UserData> map = userDataService.cacheByPartyId(partyId);
Date now = new Date();
String endTime = DateUtils.getDateStr(new Date());
String startTime = DateUtils.getDateStr(DateUtils.addDay(now, -6));
// 一周内已用额度
double withdrawMoney = withdrawMoney(map, startTime, endTime);
return withdrawMoney;
// double remain = Arith.sub(maxLimit, withdrawMoney);
// if (Arith.add(withdrawMoney, withdrawVolumn) > maxLimit) {
// throw new BusinessException("提现不得大于限额");
// }
}
/**
* 时间范围内的充值总额
*
* @param datas
* @param startTime
* @param endTime
* @return
*/
private double withdrawMoney(Map<String, UserData> datas, String startTime, String endTime) {
if (datas == null || datas.isEmpty())
return 0;
double userWithdraw = 0;
for (Entry<String, UserData> valueEntry : datas.entrySet()) {
UserData userdata = valueEntry.getValue();
Date time = userdata.getCreateTime();
if (!StringUtils.isNullOrEmpty(startTime)) {
Date startDate = DateUtils.toDate(startTime, DateUtils.DF_yyyyMMdd);
int intervalDays = DateUtils.getIntervalDaysByTwoDate(startDate, time);// 开始-数据时间
if (intervalDays > 0) // 开始>数据时间 ,则过滤
continue;
}
if (!StringUtils.isNullOrEmpty(endTime)) {
Date endDate = DateUtils.toDate(endTime, DateUtils.DF_yyyyMMdd);
int intervalDays = DateUtils.getIntervalDaysByTwoDate(endDate, time);// 结束-数据时间
if (intervalDays < 0) // 结束<数据时间
continue;
}
userWithdraw = Arith.add(userdata.getWithdraw(), userWithdraw);
}
return userWithdraw;
}
public void saveApplyOtherChannel(Withdraw withdraw, String symbol) {
Party party = this.partyService.cachePartyBy(withdraw.getPartyId(), false);
if (Constants.SECURITY_ROLE_TEST.equals(party.getRolename())) {
throw new BusinessException("无权限");
}
Kyc party_kyc = this.kycService.get(withdraw.getPartyId().toString());
// KycHighLevel party_kycHighLevel = this.kycHighLevelService.get(withdraw.getPartyId().toString());
if (!(party_kyc.getStatus() == 2) && "true".equals(sysparaService.find("withdraw_by_kyc").getValue())) {
throw new BusinessException(401, "无权限");
}
// double withdraw_by_high_kyc = Double.valueOf(sysparaService.find("withdraw_by_high_kyc").getValue());
//
// if (withdraw_by_high_kyc > 0 && withdraw.getVolume() > withdraw_by_high_kyc
// && !(party_kycHighLevel.getStatus() == 2)) {
// throw new BusinessException(1, "请先通过高级认证");
// }
if (!party.getWithdraw_authority()) {
throw new BusinessException(1, "无权限");
}
if (!party.getEnabled()) {
throw new BusinessException(506, "无权限");
}
double usdtAmount = compute2UsdtAmount(withdraw.getVolume(), symbol);
// caster 2023-8-3 注释掉该逻辑,使用 USDT 钱包余额来做校验
WalletExtend walletExtend = walletService.saveExtendByPara(party.getId(), symbol);
// if (walletExtend.getAmount() < usdtAmount) {
// throw new BusinessException(1, "余额不足");
// }
// 2023-8-3 caster 使用本方式判断余额
Wallet wallet = walletService.saveWalletByPartyId(withdraw.getPartyId());
if (wallet.getMoney() < usdtAmount) {
throw new BusinessException(1, "余额不足");
}
String withdraw_limit = sysparaService.find("withdraw_limit_" + symbol).getValue();
if (usdtAmount < Double.valueOf(withdraw_limit)) {
throw new BusinessException(1, "提现不得小于限额");
}
String withdraw_limit_max = sysparaService.find("withdraw_limit_max").getValue();
if (usdtAmount > Double.valueOf(withdraw_limit_max)) {
throw new BusinessException(1, "提现不得大于限额");
}
/**
* 当日提现次数是否超过
*/
double withdraw_limit_num = Double.valueOf(sysparaService.find("withdraw_limit_num").getValue());
List<Withdraw> withdraw_days = findAllByDate(withdraw.getPartyId().toString());
if (withdraw_limit_num > 0 && withdraw_days != null) {
if (withdraw_days.size() >= withdraw_limit_num) {
throw new BusinessException(1, "当日可提现次数不足");
}
}
/**
* 是否在当日提现时间内
*/
SimpleDateFormat sdf = new SimpleDateFormat();// 格式化时间
sdf.applyPattern("HH:mm:ss");// a为am/pm的标记
Date date = new Date();// 获取当前时间
String withdraw_limit_time = sysparaService.find("withdraw_limit_time").getValue();
if (!"".equals(withdraw_limit_time) && withdraw_limit_time != null) {
String[] withdraw_time = withdraw_limit_time.split("-");
//
String dateString = sdf.format(date);
if (dateString.compareTo(withdraw_time[0]) < 0 || dateString.compareTo(withdraw_time[1]) > 0) {
throw new BusinessException(1, "不在可提现时间内");
}
}
/**
* 可提现差额开启 取party Withdraw_limit_amount 的可提现金 和剩余金额与流水中的最小值相加
* 流水为Userdate里的交割合约理财矿池的交易量
*/
String withdraw_limit_open = sysparaService.find("withdraw_limit_open").getValue();
if ("true".equals(withdraw_limit_open)) {
// 提现限制流水开启后提现判断用的用户当前流水是使用UserData表的当日流水1还是使用Party表里的用户当前流水2
String withdraw_limit_open_use_type = sysparaService.find("withdraw_limit_open_use_type").getValue();
// 当使用userdata流水提现时提现限制流水是否加入永续合约流水1增加2不增加
String withdraw_limit_contract_or = sysparaService.find("withdraw_limit_contract_or").getValue();
if ("1".equals(withdraw_limit_open_use_type)) {
/**
* 还差多少可提现金额
*/
double fact_withdraw_amount = 0;
/**
* 用户Party表里可提现金额参数 -----可为负数
*/
double party_withdraw = party.getWithdraw_limit_amount();
/**
* usdt剩余余额
*/
// double last_usdt_amount = wallet.getMoney();
/**
* userdata交易流水
*/
double userdata_turnover = 0;
// Map<String, UserData> data_all = this.userDataService.getCache().get(withdraw.getPartyId());
Map<String, UserData> data_all = this.userDataService.cacheByPartyId(withdraw.getPartyId().toString());
if (data_all != null) {
SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMdd");
Date date_now = new Date();
for (Entry<String, UserData> valueEntry : data_all.entrySet()) {
UserData userdata = valueEntry.getValue();
// 如果日期等于当天就赋值
if (fmt.format(date_now).equals(fmt.format(userdata.getCreateTime()))) {
/**
* 永续合约下单金额amount 理财买入金额finance_amount 币币exchange_amount 矿机下单金额miner_amount
* 交割合约下单金额furtures_amount
*/
// 当使用userdata流水提现时提现限制流水是否加入永续合约流水1增加2不增加
double contract_amount = userdata.getAmount();
if ("2".equals(withdraw_limit_contract_or)) {
contract_amount = 0;
}
double amount_finance_amount = Arith.add(contract_amount, userdata.getFinance_amount());
// 币币交易流水不加入
double exchange_amount_miner_amount = Arith.add(0, userdata.getMiner_amount());
userdata_turnover = Arith.add(userdata.getFurtures_amount(),
Arith.add(amount_finance_amount, exchange_amount_miner_amount));
}
}
}
double withdraw_limit_turnover_percent = Double
.valueOf(sysparaService.find("withdraw_limit_turnover_percent").getValue());
party_withdraw = Arith.mul(party_withdraw, withdraw_limit_turnover_percent);
// 流水小于限额
if (userdata_turnover < party_withdraw) {
fact_withdraw_amount = Arith.sub(party_withdraw, userdata_turnover);
throw new BusinessException(105, fact_withdraw_amount + "");
}
}
if ("2".equals(withdraw_limit_open_use_type)) {
/**
* 还差多少可提现金额
*/
double fact_withdraw_amount = 0;
/**
* 用户Party表里可提现金额参数 -----可为负数
*/
double party_withdraw = party.getWithdraw_limit_amount();
/**
* usdt剩余余额
*/
// double last_usdt_amount = wallet.getMoney();
/**
* userdata交易流水
*/
double userdata_turnover = party.getWithdraw_limit_now_amount();
//
double withdraw_limit_turnover_percent = Double
.valueOf(sysparaService.find("withdraw_limit_turnover_percent").getValue());
party_withdraw = Arith.mul(party_withdraw, withdraw_limit_turnover_percent);
// 流水小于限额
if (userdata_turnover < party_withdraw) {
fact_withdraw_amount = Arith.sub(party_withdraw, userdata_turnover);
throw new BusinessException(105, fact_withdraw_amount + "");
}
}
}
// 计算手续费
double usdtFee = getOtherChannelWithdrawFee(usdtAmount,symbol);
withdraw.setAmount_fee(usdtFee);
// 换算成 USDT 币种后的实际到账资金
withdraw.setAmount(Arith.sub(usdtAmount, usdtFee));
// 对应提现币种下的手续费
double coinTypeFee = computeUsdt2Amount(usdtFee, symbol);
withdraw.setArrivalAmount(withdraw.getVolume() - coinTypeFee);
if ("".equals(withdraw.getOrder_no()) || withdraw.getOrder_no() == null) {
withdraw.setOrder_no(DateUtil.getToday("yyMMddHHmmss") + RandomUtil.getRandomNum(8));
}
withdraw.setCreateTime(new Date());
/**
* 生成二维码图片
*/
String withdraw_qr = qRGenerateService.generateWithdraw(withdraw.getOrder_no(), withdraw.getAddress());
withdraw.setQdcode(withdraw_qr);
// 注释旧代码
// double amount_before = walletExtend.getAmount();
double amount_before = wallet.getMoney();
// 这段代码和对应的表在充值提现业务中没看出意义所在,暂时保留
walletService.updateExtend(walletExtend.getPartyId().toString(), symbol, Arith.sub(0, withdraw.getVolume()));
this.getHibernateTemplate().save(withdraw);
// wallet.setMoney(Arith.sub(wallet.getMoney(), usdtAmount));
walletService.update(wallet.getPartyId().toString(), Arith.sub(0, usdtAmount));
/*
* 保存资金日志
*/
MoneyLog moneyLog = new MoneyLog();
moneyLog.setCategory(Constants.MONEYLOG_CATEGORY_COIN);
// 存的是 USDT 的金额
moneyLog.setAmount_before(amount_before);
// 存的是 USDT 的金额,修改
moneyLog.setAmount(Arith.sub(0, usdtAmount));
// 修改
moneyLog.setAmount_after(Arith.sub(amount_before, usdtAmount));
moneyLog.setLog("提现订单[" + withdraw.getOrder_no() + "]");
// moneyLog.setExtra(withdraw.getOrder_no());
moneyLog.setPartyId(withdraw.getPartyId());
// 2023-8-3 caster 修改为 USDT查看其他币种充值时moneyLog 记录使用的也是 USDT 单位来存储数据
moneyLog.setWallettype(Constants.WALLET);
// moneyLog.setWallettype(symbol.toUpperCase());
moneyLog.setContent_type(Constants.MONEYLOG_CONTENT_WITHDRAW);
moneyLogService.save(moneyLog);
/*
* 保存资金日志
*/
WalletLog walletLog = new WalletLog();
walletLog.setCategory("withdraw");
walletLog.setPartyId(withdraw.getPartyId());
walletLog.setOrder_no(withdraw.getOrder_no());
walletLog.setStatus(withdraw.getSucceeded());
walletLog.setAmount(withdraw.getVolume());
// 换算成USDT单位
walletLog.setUsdtAmount(usdtAmount);
walletLog.setWallettype(symbol.toUpperCase());
walletLogService.save(walletLog);
tipService.saveTip(withdraw.getId().toString(), TipConstants.WITHDRAW);
}
/**
* 获取其他通道的手续费
*
* @param volume 提现数量
* @return
*/
public double getOtherChannelWithdrawFee(double volume,String symbol) {
/**
* 提现手续费part分段的值
*/
String withdraw_fee_part = null;
if ("btc".equals(symbol)) {
withdraw_fee_part = sysparaService.find("withdraw_other_channel_fee_part_btc").getValue();
}else if("eth".equals(symbol)){
withdraw_fee_part = sysparaService.find("withdraw_other_channel_fee_part_eth").getValue();
}
// 之前的实现方式为 分段 参数为 '1000,0.03,999999999999,0.03',现在改为固定费率不分段
// double fee = 0;
/*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 (volume <= part_amount) {
fee = Arith.mul(part_fee, volume);
break;
}
i++;
}*/
double fee = Arith.mul(volume,Arith.div(Double.valueOf(withdraw_fee_part),100));
return Arith.roundDown(fee, 6);
}
@Override
public Withdraw findByOrderNo(String order_no) {
StringBuffer queryString = new StringBuffer(" FROM Withdraw where order_no=?0");
List<Withdraw> list = (List<Withdraw>) getHibernateTemplate().find(queryString.toString(), new Object[] { order_no });
if (list.size() > 0) {
return list.get(0);
}
return null;
}
public boolean saveReject(Withdraw withdraw) {
if (withdraw.getSucceeded() == 2 || withdraw.getSucceeded() == 1) {// 通过后不可驳回
return false;
}
withdraw.setSucceeded(2);
String symbol = "";
if (withdraw.getMethod().indexOf("BTC") != -1) {
symbol = "btc";
} else if (withdraw.getMethod().indexOf("ETH") != -1) {
symbol = "eth";
} else {
symbol = "usdt";
}
if ("usdt".equals(symbol)) {
Wallet wallet = walletService.saveWalletByPartyId(withdraw.getPartyId());
double amount_before = wallet.getMoney();
walletService.update(wallet.getPartyId().toString(),
Arith.add(withdraw.getAmount(), withdraw.getAmount_fee()));
/*
* 保存资金日志
*/
MoneyLog moneyLog = new MoneyLog();
moneyLog.setCategory(Constants.MONEYLOG_CATEGORY_COIN);
moneyLog.setAmount_before(amount_before);
moneyLog.setAmount(Arith.add(withdraw.getAmount(), withdraw.getAmount_fee()));
moneyLog.setAmount_after(Arith.add(amount_before, Arith.add(withdraw.getAmount(), withdraw.getAmount_fee())));
moneyLog.setLog("驳回提现[" + withdraw.getOrder_no() + "]");
// moneyLog.setExtra(withdraw.getOrder_no());
moneyLog.setPartyId(withdraw.getPartyId());
moneyLog.setWallettype(Constants.WALLET);
moneyLog.setContent_type(Constants.MONEYLOG_CONTENT_WITHDRAW);
moneyLogService.save(moneyLog);
} else {
WalletExtend walletExtend = walletService.saveExtendByPara(withdraw.getPartyId(), symbol);
double amount_before = walletExtend.getAmount();
walletService.updateExtend(withdraw.getPartyId().toString(), symbol, withdraw.getVolume());
/*
* 保存资金日志
*/
MoneyLog moneyLog = new MoneyLog();
moneyLog.setCategory(Constants.MONEYLOG_CATEGORY_COIN);
moneyLog.setAmount_before(amount_before);
moneyLog.setAmount(withdraw.getVolume());
moneyLog.setAmount_after(Arith.add(amount_before, withdraw.getVolume()));
moneyLog.setLog("驳回提现[" + withdraw.getOrder_no() + "]");
// moneyLog.setExtra(withdraw.getOrder_no());
moneyLog.setPartyId(withdraw.getPartyId());
moneyLog.setWallettype(symbol.toUpperCase());
moneyLog.setContent_type(Constants.MONEYLOG_CONTENT_WITHDRAW);
moneyLogService.save(moneyLog);
}
this.update(withdraw);
this.walletLogService.updateStatus(withdraw.getOrder_no(), withdraw.getSucceeded());
return true;
}
public List<Withdraw> findAllByDate(String partyId) {
List<Withdraw> list = (List<Withdraw>) this.getHibernateTemplate()
.find(" FROM Withdraw WHERE partyId=?0 AND DateDiff(createTime,NOW())=0 ", new Object[] { partyId });
return list;
}
public List<Withdraw> findAllByStateAndPartyId(int state, String partyId) {
List<Withdraw> list = (List<Withdraw>) this.getHibernateTemplate().find(" FROM Withdraw WHERE partyId=?0 AND succeeded=?1 ",
new Object[] { partyId, state });
return list;
}
@Override
public List<Withdraw> selectWithdraw(String partyId) {
return (List<Withdraw>) getHibernateTemplate().find("FROM Withdraw WHERE to_days(CREATE_TIME) = to_days(now()) and partyId=?0 ",
new Object[] { partyId });
}
public void update(Withdraw withdraw) {
this.getHibernateTemplate().update(withdraw);
}
@Override
public List<Withdraw> selectUnFinishedWithdraw(String partyId) {
return (List<Withdraw>) getHibernateTemplate().find("FROM Withdraw WHERE partyId=?0 and succeeded=0 ",
new Object[] { partyId });
}
/**
* 将指定币种的值转化成 USDT 币种对应的金额.
*
* @param amount
* @param coinType
* @return
*/
protected double compute2UsdtAmount(double amount, String coinType) {
if (StrUtil.isBlank(coinType)) {
throw new BusinessException("参数错误");
}
double fee = 0.0;
if (coinType.equalsIgnoreCase("BTC")) {
fee = Double.parseDouble(hobiDataService.getSymbolRealPrize("btc"));
} else if (coinType.equalsIgnoreCase("ETH")) {
fee = Double.parseDouble(hobiDataService.getSymbolRealPrize("eth"));
} else {
// USDT、USDC 币种也支持 ERC20 类型的链,经同事确认也是比率 1:1
fee = 1;
}
return Arith.roundDown(Arith.mul(amount, fee), 6);
}
/**
* 将 usdt 币种对应的金额转化成指定币种的值.
*
* @param usdtAmount
* @param coinType
* @return
*/
protected double computeUsdt2Amount(double usdtAmount, String coinType) {
if (StrUtil.isBlank(coinType)) {
throw new BusinessException("参数错误");
}
double fee = 0.0;
if (coinType.equalsIgnoreCase("BTC")) {
fee = Double.parseDouble(hobiDataService.getSymbolRealPrize("btc"));
} else if (coinType.equalsIgnoreCase("ETH")) {
fee = Double.parseDouble(hobiDataService.getSymbolRealPrize("eth"));
} else {
// USDT、USDC 币种也支持 ERC20 类型的链,经同事确认也是比率 1:1
fee = 1;
}
return Arith.roundDown(Arith.div(usdtAmount, fee), 6);
}
public void setSysparaService(SysparaService sysparaService) {
this.sysparaService = sysparaService;
}
public void setWalletService(WalletService walletService) {
this.walletService = walletService;
}
public void setMoneyLogService(MoneyLogService moneyLogService) {
this.moneyLogService = moneyLogService;
}
public void setExchangeRateService(ExchangeRateService exchangeRateService) {
this.exchangeRateService = exchangeRateService;
}
// public void setPaymentMethodService(PaymentMethodService paymentMethodService) {
// this.paymentMethodService = paymentMethodService;
// }
public void setWalletLogService(WalletLogService walletLogService) {
this.walletLogService = walletLogService;
}
public void setqRGenerateService(QRGenerateService qRGenerateService) {
this.qRGenerateService = qRGenerateService;
}
@Override
public boolean saveSucceeded(Withdraw withdraw) {
if (withdraw.getSucceeded() == 1) {
return false;
}
withdraw.setSucceeded(1);
String symbol = "";
if (withdraw.getMethod().indexOf("BTC") != -1) {
symbol = "btc";
} else if (withdraw.getMethod().indexOf("ETH") != -1) {
symbol = "eth";
} else {
symbol = "usdt";
}
this.walletLogService.updateStatus(withdraw.getOrder_no(), withdraw.getSucceeded());
/**
* 提现订单加入userdate
*/
this.userDataService.saveWithdrawHandle(withdraw.getPartyId(), withdraw.getAmount(), withdraw.getAmount_fee(),
symbol);
this.update(withdraw);
return true;
}
public void setUserDataService(UserDataService userDataService) {
this.userDataService = userDataService;
}
public void setPartyService(PartyService partyService) {
this.partyService = partyService;
}
public void setKycService(KycService kycService) {
this.kycService = kycService;
}
// public void setKycHighLevelService(KycHighLevelService kycHighLevelService) {
// this.kycHighLevelService = kycHighLevelService;
// }
public void setTipService(TipService tipService) {
this.tipService = tipService;
}
public void setHobiDataService(HobiDataService hobiDataService) {
this.hobiDataService = hobiDataService;
}
}