Compare commits
55 Commits
a0750e1246
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 2fedb72480 | |||
| f4566777d7 | |||
| 10d85fe508 | |||
| 066c3b48f6 | |||
| 4462ba7e7e | |||
| 3bf81f5749 | |||
| da64a7a517 | |||
| 4929188dd7 | |||
| db21058db1 | |||
| 6ed6c2fc70 | |||
| 4e9d55aab6 | |||
| 2efa65222d | |||
| ef395c5253 | |||
| 7161e6fe57 | |||
| 6bd204dc4b | |||
| f0a2309b42 | |||
| ec8faeb41d | |||
| a9ddc0b9d3 | |||
| 182a2d6c43 | |||
| 981838726c | |||
| f8264b2df1 | |||
| 80b15dcf5b | |||
| 7258909381 | |||
| 94899a4baa | |||
| 95573662ff | |||
| c73dc4db7b | |||
| 00c490d28f | |||
| b43e8f9965 | |||
| 0857913e54 | |||
| a51771db2e | |||
| c698a8244c | |||
| 5a8e59336a | |||
| 0b2decafc9 | |||
| 315079e5d1 | |||
| 4fad507896 | |||
| 1ea709d1a8 | |||
| eeee428a94 | |||
| 9ae9a88a46 | |||
| 3e2178e161 | |||
| ca86a560dc | |||
| ffff88bacf | |||
| 9904fbeb24 | |||
| d098702af7 | |||
| f65f08d1a6 | |||
| 65bd4c90c1 | |||
| 6b72064d5c | |||
| b6b26e591f | |||
| 779aaca109 | |||
| 5d7e3e6401 | |||
| 86bb162b16 | |||
| 88ea456424 | |||
| e3e7993134 | |||
| b1d1a3a93e | |||
| 31e0f400d9 | |||
| 40f4cd0007 |
@@ -3,6 +3,7 @@ package com.m2pool.system.api;
|
|||||||
import com.m2pool.common.core.Result.R;
|
import com.m2pool.common.core.Result.R;
|
||||||
import com.m2pool.common.core.constant.ServiceNameConstants;
|
import com.m2pool.common.core.constant.ServiceNameConstants;
|
||||||
import com.m2pool.system.api.entity.EmailEntity;
|
import com.m2pool.system.api.entity.EmailEntity;
|
||||||
|
import com.m2pool.system.api.entity.EmailTemplateEntity;
|
||||||
import com.m2pool.system.api.entity.GetEmailCodeEntity;
|
import com.m2pool.system.api.entity.GetEmailCodeEntity;
|
||||||
import com.m2pool.system.api.factory.RemoteMailFallbackFactory;
|
import com.m2pool.system.api.factory.RemoteMailFallbackFactory;
|
||||||
import org.springframework.cloud.openfeign.FeignClient;
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
@@ -32,5 +33,14 @@ public interface RemoteMailService
|
|||||||
*/
|
*/
|
||||||
@PostMapping("/sendTextMail")
|
@PostMapping("/sendTextMail")
|
||||||
public R<?> sendTextMail(@RequestBody EmailEntity entity);
|
public R<?> sendTextMail(@RequestBody EmailEntity entity);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送html邮件
|
||||||
|
*
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
@PostMapping("/sendHtmlMailMessage")
|
||||||
|
public R<?> sendHtmlMailMessage(@RequestBody EmailTemplateEntity entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.m2pool.system.api.factory;
|
|||||||
import com.m2pool.common.core.Result.R;
|
import com.m2pool.common.core.Result.R;
|
||||||
import com.m2pool.system.api.RemoteMailService;
|
import com.m2pool.system.api.RemoteMailService;
|
||||||
import com.m2pool.system.api.entity.EmailEntity;
|
import com.m2pool.system.api.entity.EmailEntity;
|
||||||
|
import com.m2pool.system.api.entity.EmailTemplateEntity;
|
||||||
import com.m2pool.system.api.entity.GetEmailCodeEntity;
|
import com.m2pool.system.api.entity.GetEmailCodeEntity;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -35,6 +36,11 @@ public class RemoteMailFallbackFactory implements FallbackFactory<RemoteMailServ
|
|||||||
return R.fail("邮箱发送失败:" + cause.getMessage());
|
return R.fail("邮箱发送失败:" + cause.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public R<?> sendHtmlMailMessage(@RequestBody EmailTemplateEntity entity) {
|
||||||
|
return R.fail("邮箱发送失败:" + cause.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package com.m2pool.system.api.model;
|
package com.m2pool.system.api.model;
|
||||||
|
|
||||||
import com.m2pool.system.api.entity.SysUser;
|
import com.m2pool.system.api.entity.SysUser;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@@ -12,35 +14,45 @@ import java.util.Set;
|
|||||||
* @Author dy
|
* @Author dy
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
|
@ApiModel(description = "登录用户信息")
|
||||||
public class LoginUser implements Serializable {
|
public class LoginUser implements Serializable {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
/** 用户唯一标识 */
|
/** 用户唯一标识 */
|
||||||
|
@ApiModelProperty(value = "用户唯一标识")
|
||||||
private String token;
|
private String token;
|
||||||
|
|
||||||
/** 用户名id */
|
/** 用户名id */
|
||||||
|
@ApiModelProperty(value = "用户名id")
|
||||||
private Long userid;
|
private Long userid;
|
||||||
|
|
||||||
/** 用户名 */
|
/** 用户名 */
|
||||||
|
@ApiModelProperty(value = "用户名")
|
||||||
private String username;
|
private String username;
|
||||||
|
|
||||||
/** 登录时间 */
|
/** 登录时间 */
|
||||||
|
@ApiModelProperty(value = "登录时间")
|
||||||
private Long loginTime;
|
private Long loginTime;
|
||||||
|
|
||||||
/** 过期时间 */
|
/** 过期时间 */
|
||||||
|
@ApiModelProperty(value = "过期时间")
|
||||||
private Long expireTime;
|
private Long expireTime;
|
||||||
|
|
||||||
/** 登录IP地址 */
|
/** 登录IP地址 */
|
||||||
|
@ApiModelProperty(value = "登录IP地址")
|
||||||
private String ipaddr;
|
private String ipaddr;
|
||||||
|
|
||||||
/** 权限列表 */
|
/** 权限列表 */
|
||||||
|
@ApiModelProperty(value = "权限列表")
|
||||||
private Set<String> permissions;
|
private Set<String> permissions;
|
||||||
|
|
||||||
/** 角色列表 */
|
/** 角色列表 */
|
||||||
|
@ApiModelProperty(value = "角色列表")
|
||||||
private Set<String> roles;
|
private Set<String> roles;
|
||||||
|
|
||||||
/** 用户信息 */
|
/** 用户信息 */
|
||||||
|
@ApiModelProperty(value = "用户详情信息对象")
|
||||||
private SysUser sysUser;
|
private SysUser sysUser;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,18 @@
|
|||||||
<artifactId>common-security</artifactId>
|
<artifactId>common-security</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Thymeleaf 用于发送邮箱 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mapstruct</groupId>
|
||||||
|
<artifactId>mapstruct</artifactId>
|
||||||
|
<version>1.5.0.RC1</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
@@ -6,12 +6,11 @@ import com.m2pool.auth.service.impl.MaliServiceImpl;
|
|||||||
import com.m2pool.common.core.Result.R;
|
import com.m2pool.common.core.Result.R;
|
||||||
import com.m2pool.common.core.utils.JwtUtils;
|
import com.m2pool.common.core.utils.JwtUtils;
|
||||||
import com.m2pool.common.core.utils.StringUtils;
|
import com.m2pool.common.core.utils.StringUtils;
|
||||||
import com.m2pool.common.core.web.Result.AjaxResult;
|
|
||||||
import com.m2pool.common.security.annotation.RequiresLogin;
|
import com.m2pool.common.security.annotation.RequiresLogin;
|
||||||
import com.m2pool.common.security.auth.AuthUtil;
|
import com.m2pool.common.security.auth.AuthUtil;
|
||||||
import com.m2pool.common.security.service.TokenService;
|
import com.m2pool.common.security.service.TokenService;
|
||||||
import com.m2pool.common.security.utils.SecurityUtils;
|
import com.m2pool.common.security.utils.SecurityUtils;
|
||||||
import com.m2pool.system.api.entity.SysUser;
|
import com.m2pool.system.api.entity.EmailTemplateEntity;
|
||||||
import com.m2pool.system.api.model.LoginUser;
|
import com.m2pool.system.api.model.LoginUser;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
@@ -22,6 +21,7 @@ import org.springframework.web.bind.annotation.*;
|
|||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -49,6 +49,19 @@ public class TokenController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 后台管理系统登录
|
||||||
|
* @param loginManageBody
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@PostMapping("managerLogin")
|
||||||
|
@ApiOperation(value = "后台管理系统登录")
|
||||||
|
public R<Map<String,Object>> managerLogin(@RequestBody @Valid LoginManageBody loginManageBody)
|
||||||
|
{
|
||||||
|
return sysLoginService.managerLogin(loginManageBody);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@PostMapping("registerCode")
|
@PostMapping("registerCode")
|
||||||
public R<?> emailCode(@Validated @RequestBody GetEmailCodeEntity entity)
|
public R<?> emailCode(@Validated @RequestBody GetEmailCodeEntity entity)
|
||||||
{
|
{
|
||||||
@@ -125,7 +138,7 @@ public class TokenController {
|
|||||||
public R<?> resetPwd(@Valid @RequestBody ResetPwdBody resetPwdBody)
|
public R<?> resetPwd(@Valid @RequestBody ResetPwdBody resetPwdBody)
|
||||||
{
|
{
|
||||||
// 重置密码
|
// 重置密码
|
||||||
sysLoginService.resetPwd(resetPwdBody);
|
sysLoginService.resetPwd(resetPwdBody,true);
|
||||||
return R.success("账号"+ resetPwdBody.getEmail()+"密码重置成功");
|
return R.success("账号"+ resetPwdBody.getEmail()+"密码重置成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,7 +150,7 @@ public class TokenController {
|
|||||||
resetPwdBody.setEmail(email);
|
resetPwdBody.setEmail(email);
|
||||||
|
|
||||||
// 修改密码
|
// 修改密码
|
||||||
sysLoginService.resetPwd(resetPwdBody);
|
sysLoginService.resetPwd(resetPwdBody,false);
|
||||||
return R.success("账号"+ resetPwdBody.getEmail()+"密码修改成功");
|
return R.success("账号"+ resetPwdBody.getEmail()+"密码修改成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,4 +162,13 @@ public class TokenController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@PostMapping("sendHtmlMailMessage")
|
||||||
|
public R<?> sendHtmlMailMessage(@Valid @RequestBody EmailTemplateEntity entity)
|
||||||
|
{
|
||||||
|
maliService.sendHtmlMailMessage(entity);
|
||||||
|
return R.success("邮件已发送");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package com.m2pool.auth.entity;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.constraints.Email;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description 管理系统用户登录请求对象
|
||||||
|
* @Date 2025/5/22 16:13
|
||||||
|
* @Author yyb
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@ApiModel(description = "")
|
||||||
|
public class LoginManageBody {
|
||||||
|
|
||||||
|
/** 邮箱 */
|
||||||
|
@Email
|
||||||
|
@ApiModelProperty(value = "邮箱", required = true, example = "")
|
||||||
|
private String userName;
|
||||||
|
|
||||||
|
/** 密码 */
|
||||||
|
@ApiModelProperty(value = "密码", required = true, example = "")
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
private String uuid;
|
||||||
|
|
||||||
|
//private boolean flag = false;
|
||||||
|
}
|
||||||
@@ -19,6 +19,8 @@ public class ResetPwdBody {
|
|||||||
|
|
||||||
private String resetPwdCode;
|
private String resetPwdCode;
|
||||||
|
|
||||||
|
private String updatePwdCode;
|
||||||
|
|
||||||
/** 新密码 */
|
/** 新密码 */
|
||||||
private String password;
|
private String password;
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.m2pool.auth.service;
|
|||||||
import com.m2pool.auth.entity.GetEmailCodeEntity;
|
import com.m2pool.auth.entity.GetEmailCodeEntity;
|
||||||
import com.m2pool.auth.entity.GetLoginEmailCodeEntity;
|
import com.m2pool.auth.entity.GetLoginEmailCodeEntity;
|
||||||
import com.m2pool.common.core.Result.R;
|
import com.m2pool.common.core.Result.R;
|
||||||
|
import com.m2pool.system.api.entity.EmailTemplateEntity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description TODO
|
* @Description TODO
|
||||||
@@ -19,12 +20,9 @@ public interface MailService {
|
|||||||
public void sendTextMailMessage(String to,String subject,String text);
|
public void sendTextMailMessage(String to,String subject,String text);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发送html邮件
|
* 发送矿机离线数 html邮件
|
||||||
* @param to
|
|
||||||
* @param subject
|
|
||||||
* @param content
|
|
||||||
*/
|
*/
|
||||||
public void sendHtmlMailMessage(String to,String subject,String content);
|
public void sendHtmlMailMessage(EmailTemplateEntity entity);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发送带附件的邮件
|
* 发送带附件的邮件
|
||||||
|
|||||||
@@ -25,10 +25,15 @@ import com.m2pool.system.api.RemoteUserService;
|
|||||||
import com.m2pool.system.api.entity.SysLogininfor;
|
import com.m2pool.system.api.entity.SysLogininfor;
|
||||||
import com.m2pool.system.api.entity.SysUser;
|
import com.m2pool.system.api.entity.SysUser;
|
||||||
import com.m2pool.system.api.model.LoginUser;
|
import com.m2pool.system.api.model.LoginUser;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.ibatis.annotations.Update;
|
import org.apache.ibatis.annotations.Update;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
|
||||||
@@ -37,6 +42,7 @@ import java.util.concurrent.TimeUnit;
|
|||||||
* @Date 2024/6/12 16:19
|
* @Date 2024/6/12 16:19
|
||||||
* @Author dy
|
* @Author dy
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
@Component
|
@Component
|
||||||
public class SysLoginService {
|
public class SysLoginService {
|
||||||
|
|
||||||
@@ -232,6 +238,86 @@ public class SysLoginService {
|
|||||||
return R.success(tokenService.createToken(userInfo));
|
return R.success(tokenService.createToken(userInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public R<Map<String,Object>> managerLogin(LoginManageBody loginManageBody){
|
||||||
|
//邮箱
|
||||||
|
String email = loginManageBody.getUserName();
|
||||||
|
|
||||||
|
//String password= loginBody.getPassword();
|
||||||
|
String password="";
|
||||||
|
|
||||||
|
try {
|
||||||
|
password = RsaUtils.decryptByPrivateKey(loginManageBody.getPassword());
|
||||||
|
password = StringUtils.clean(password);
|
||||||
|
}catch (Exception e){
|
||||||
|
return R.fail(401,"加密密码传参有误");
|
||||||
|
}
|
||||||
|
// 用户名或密码为空 错误
|
||||||
|
if (StringUtils.isAnyBlank(email, password))
|
||||||
|
{
|
||||||
|
recordLogininfor(email, Constants.LOGIN_FAIL, "邮箱/密码必须填写");
|
||||||
|
throw new ServiceException("邮箱/密码必须填写");
|
||||||
|
}
|
||||||
|
if(!StringUtils.isBlank(email)){
|
||||||
|
if(!email.matches(EMAIL_REGEX)){
|
||||||
|
throw new ServiceException("邮箱格式错误");
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
throw new ServiceException("邮箱为必填项");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 密码如果不在指定范围内 错误
|
||||||
|
if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
|
||||||
|
|| password.length() > UserConstants.PASSWORD_MAX_LENGTH)
|
||||||
|
{
|
||||||
|
recordLogininfor(email, Constants.LOGIN_FAIL, "用户密码不在指定范围");
|
||||||
|
throw new ServiceException("用户密码不在指定范围");
|
||||||
|
}
|
||||||
|
// 查询用户信息
|
||||||
|
R<LoginUser> userResult = remoteUserService.getUserInfo(email, SecurityConstants.INNER);
|
||||||
|
|
||||||
|
if (R.FAIL == userResult.getCode())
|
||||||
|
{
|
||||||
|
throw new ServiceException(userResult.getMsg());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringUtils.isNull(userResult.getData()))
|
||||||
|
{
|
||||||
|
recordLogininfor(email, Constants.LOGIN_FAIL, "登录用户不存在");
|
||||||
|
throw new ServiceException("登录用户:" + email + " 不存在");
|
||||||
|
}
|
||||||
|
LoginUser userInfo = userResult.getData();
|
||||||
|
SysUser user = userResult.getData().getSysUser();
|
||||||
|
Set<String> roles = userInfo.getRoles();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
|
||||||
|
{
|
||||||
|
recordLogininfor(email, Constants.LOGIN_FAIL, "对不起,您的账号已被删除");
|
||||||
|
throw new ServiceException("对不起,您的账号:" + email + " 已被删除");
|
||||||
|
}
|
||||||
|
if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
|
||||||
|
{
|
||||||
|
recordLogininfor(email, Constants.LOGIN_FAIL, "用户已停用,请联系管理员");
|
||||||
|
throw new ServiceException("对不起,您的账号:" + email + " 已停用");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!SecurityUtils.matchesPassword(password, user.getPassword())){
|
||||||
|
throw new ServiceException("密码错误,请重新输入");
|
||||||
|
}
|
||||||
|
|
||||||
|
//必须是管理员才能登录
|
||||||
|
if(!roles.contains("3")){
|
||||||
|
recordLogininfor(email, Constants.LOGIN_FAIL, "对不起,您的账号没有权限不能登录后台管理");
|
||||||
|
throw new ServiceException("对不起,您的账号:" + email + " 没有权限不能登录后台管理");
|
||||||
|
}
|
||||||
|
|
||||||
|
recordLogininfor(email, Constants.LOGIN_SUCCESS, "后台管理系统用户登录成功");
|
||||||
|
|
||||||
|
return R.success(tokenService.createToken(userInfo));
|
||||||
|
}
|
||||||
|
|
||||||
public void logout(String loginName)
|
public void logout(String loginName)
|
||||||
{
|
{
|
||||||
recordLogininfor(loginName, Constants.LOGOUT, "退出成功");
|
recordLogininfor(loginName, Constants.LOGOUT, "退出成功");
|
||||||
@@ -320,11 +406,11 @@ public class SysLoginService {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 重置密码
|
*
|
||||||
*/
|
*/
|
||||||
public void resetPwd(ResetPwdBody resetPwdBody)
|
public void resetPwd(ResetPwdBody resetPwdBody,boolean isUpdate)
|
||||||
{
|
{
|
||||||
|
log.info("验证码{},重置密码{},重置者邮箱{}",resetPwdBody.getResetPwdCode(),resetPwdBody.getPassword(),resetPwdBody.getEmail());
|
||||||
String password = resetPwdBody.getPassword();
|
String password = resetPwdBody.getPassword();
|
||||||
try {
|
try {
|
||||||
password = RsaUtils.decryptByPrivateKey(resetPwdBody.getPassword());
|
password = RsaUtils.decryptByPrivateKey(resetPwdBody.getPassword());
|
||||||
@@ -335,6 +421,7 @@ public class SysLoginService {
|
|||||||
|
|
||||||
String email = resetPwdBody.getEmail();
|
String email = resetPwdBody.getEmail();
|
||||||
String resetPwdCode = resetPwdBody.getResetPwdCode();
|
String resetPwdCode = resetPwdBody.getResetPwdCode();
|
||||||
|
String updatePwdCode = resetPwdBody.getUpdatePwdCode();
|
||||||
// 邮箱或密码为空 错误
|
// 邮箱或密码为空 错误
|
||||||
if (StringUtils.isAnyBlank(email, password))
|
if (StringUtils.isAnyBlank(email, password))
|
||||||
{
|
{
|
||||||
@@ -382,8 +469,9 @@ public class SysLoginService {
|
|||||||
//
|
//
|
||||||
//System.out.println(checkCodeResult);
|
//System.out.println(checkCodeResult);
|
||||||
|
|
||||||
if(redisService.hasKey(RedisTransKey.getResetPwdKey(email))){
|
log.info("重置密码{},修改验证码{},重置验证码{}",isUpdate,redisService.hasKey(RedisTransKey.getResetPwdKey(email)),redisService.hasKey(RedisTransKey.getUpdatePwdKey(email)));
|
||||||
|
// 如果是true代表就是忘记密码 false 就是个人中心重置密码
|
||||||
|
if(isUpdate && redisService.hasKey(RedisTransKey.getResetPwdKey(email))){
|
||||||
Object o = redisService.getCacheObject(RedisTransKey.getResetPwdKey(email));//user:emailCode:username
|
Object o = redisService.getCacheObject(RedisTransKey.getResetPwdKey(email));//user:emailCode:username
|
||||||
|
|
||||||
EmailCodeEntity emailCodeEntity = JSON.parseObject(JSON.toJSONString(o), EmailCodeEntity.class);
|
EmailCodeEntity emailCodeEntity = JSON.parseObject(JSON.toJSONString(o), EmailCodeEntity.class);
|
||||||
@@ -409,6 +497,32 @@ public class SysLoginService {
|
|||||||
}else {
|
}else {
|
||||||
throw new ServiceException("请勿修改已输入的邮箱");
|
throw new ServiceException("请勿修改已输入的邮箱");
|
||||||
}
|
}
|
||||||
|
}else if(!isUpdate && redisService.hasKey(RedisTransKey.getUpdatePwdKey(email))){
|
||||||
|
Object o = redisService.getCacheObject(RedisTransKey.getUpdatePwdKey(email));//user:emailCode:username
|
||||||
|
|
||||||
|
EmailCodeEntity emailCodeEntity = JSON.parseObject(JSON.toJSONString(o), EmailCodeEntity.class);
|
||||||
|
if (email.equals(emailCodeEntity.getEmail())) {
|
||||||
|
//邮箱必须和刚刚传的一致
|
||||||
|
//验证验证码
|
||||||
|
if(updatePwdCode.equals(emailCodeEntity.getEmailCode())){
|
||||||
|
// 重置用户密码
|
||||||
|
SysUser sysUser = new SysUser();
|
||||||
|
sysUser.setEmail(email);
|
||||||
|
sysUser.setPassword(SecurityUtils.encryptPassword(password));
|
||||||
|
|
||||||
|
R<?> resetPwdResult = remoteUserService.resetPwdByEmail(sysUser);
|
||||||
|
|
||||||
|
if (R.FAIL == resetPwdResult.getCode())
|
||||||
|
{
|
||||||
|
throw new ServiceException(resetPwdResult.getMsg());
|
||||||
|
}
|
||||||
|
//recordLogininfor(username, Constants.REGISTER, "注册成功");
|
||||||
|
}else {
|
||||||
|
throw new ServiceException("邮箱验证码错误");
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
throw new ServiceException("请勿修改已输入的邮箱");
|
||||||
|
}
|
||||||
}else {
|
}else {
|
||||||
////判断是邮箱不存在还是操作超时
|
////判断是邮箱不存在还是操作超时
|
||||||
////通过邮箱获取用户
|
////通过邮箱获取用户
|
||||||
@@ -419,7 +533,6 @@ public class SysLoginService {
|
|||||||
//}
|
//}
|
||||||
throw new ServiceException("验证码校验失败:操作超时,请重新操作");
|
throw new ServiceException("验证码校验失败:操作超时,请重新操作");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,12 +8,12 @@ import com.m2pool.auth.service.MailService;
|
|||||||
import com.m2pool.common.core.RedisTransKey;
|
import com.m2pool.common.core.RedisTransKey;
|
||||||
import com.m2pool.common.core.Result.R;
|
import com.m2pool.common.core.Result.R;
|
||||||
import com.m2pool.common.core.constant.SecurityConstants;
|
import com.m2pool.common.core.constant.SecurityConstants;
|
||||||
import com.m2pool.common.core.exception.ServiceException;
|
|
||||||
import com.m2pool.common.core.utils.CodeUtils;
|
import com.m2pool.common.core.utils.CodeUtils;
|
||||||
import com.m2pool.common.core.utils.StringUtils;
|
import com.m2pool.common.core.utils.StringUtils;
|
||||||
import com.m2pool.common.redis.service.RedisService;
|
import com.m2pool.common.redis.service.RedisService;
|
||||||
import com.m2pool.common.security.utils.SecurityUtils;
|
import com.m2pool.common.security.utils.SecurityUtils;
|
||||||
import com.m2pool.system.api.RemoteUserService;
|
import com.m2pool.system.api.RemoteUserService;
|
||||||
|
import com.m2pool.system.api.entity.EmailTemplateEntity;
|
||||||
import com.m2pool.system.api.model.LoginUser;
|
import com.m2pool.system.api.model.LoginUser;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
@@ -21,9 +21,15 @@ import org.springframework.core.io.FileSystemResource;
|
|||||||
import org.springframework.mail.javamail.JavaMailSenderImpl;
|
import org.springframework.mail.javamail.JavaMailSenderImpl;
|
||||||
import org.springframework.mail.javamail.MimeMessageHelper;
|
import org.springframework.mail.javamail.MimeMessageHelper;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.thymeleaf.TemplateEngine;
|
||||||
|
import org.thymeleaf.context.Context;
|
||||||
|
|
||||||
|
import javax.mail.MessagingException;
|
||||||
|
import javax.mail.internet.MimeMessage;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -42,12 +48,19 @@ public class MaliServiceImpl implements MailService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private RemoteUserService remoteUserService;
|
private RemoteUserService remoteUserService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private TemplateEngine templateEngine;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private RedisService redisService;
|
private RedisService redisService;
|
||||||
|
|
||||||
@Value("${spring.mail.username}")
|
@Value("${spring.mail.username}")
|
||||||
private String sendMailer;
|
private String sendMailer;
|
||||||
|
|
||||||
|
|
||||||
|
@Value("${image.prefix}")
|
||||||
|
private String imagePrefix;
|
||||||
|
|
||||||
public static String EMAIL_REGEX="^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$";
|
public static String EMAIL_REGEX="^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -103,42 +116,52 @@ public class MaliServiceImpl implements MailService {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发送html邮件
|
* 发送HTML邮件
|
||||||
* @param to
|
* @param to
|
||||||
* @param subject
|
* @param subject
|
||||||
* @param content
|
* @param templateName 模版名
|
||||||
|
* @param variables 需要映射到html上的动态内容
|
||||||
|
* @throws MessagingException
|
||||||
*/
|
*/
|
||||||
|
public void sendHtmlEmail(String to, String subject, String templateName, Map<String, Object> variables) throws MessagingException {
|
||||||
|
// 创建 MimeMessage 对象
|
||||||
|
MimeMessage message = javaMailSender.createMimeMessage();
|
||||||
|
MimeMessageHelper helper = new MimeMessageHelper(message, true);
|
||||||
|
|
||||||
|
|
||||||
|
//邮件发信人
|
||||||
|
helper.setFrom(sendMailer);
|
||||||
|
|
||||||
|
// 收件人一个活多个
|
||||||
|
helper.setTo(to.split(","));
|
||||||
|
helper.setSubject(subject);
|
||||||
|
|
||||||
|
// 创建 Thymeleaf 上下文并添加变量
|
||||||
|
Context context = new Context();
|
||||||
|
//设置图片访问前缀
|
||||||
|
variables.put("imagePrefix", imagePrefix);
|
||||||
|
context.setVariables(variables);
|
||||||
|
|
||||||
|
// 处理 HTML 模板
|
||||||
|
String htmlContent = templateEngine.process(templateName, context);
|
||||||
|
|
||||||
|
// 设置邮件内容为 HTML
|
||||||
|
helper.setText(htmlContent, true);
|
||||||
|
|
||||||
|
//邮件发送时间
|
||||||
|
helper.setSentDate(new Date());
|
||||||
|
|
||||||
|
// 发送邮件
|
||||||
|
javaMailSender.send(message);
|
||||||
|
System.out.println("发送邮件成功:"+sendMailer+"->"+to);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendHtmlMailMessage(String to,String subject,String content){
|
public void sendHtmlMailMessage(EmailTemplateEntity entity){
|
||||||
|
|
||||||
content="<!DOCTYPE html>\n" +
|
|
||||||
"<html>\n" +
|
|
||||||
"<head>\n" +
|
|
||||||
"<meta charset=\"utf-8\">\n" +
|
|
||||||
"<title>邮件</title>\n" +
|
|
||||||
"</head>\n" +
|
|
||||||
"<body>\n" +
|
|
||||||
"\t<h3>这是一封HTML邮件!</h3>\n" +
|
|
||||||
"</body>\n" +
|
|
||||||
"</html>";
|
|
||||||
try {
|
try {
|
||||||
//true 代表支持复杂的类型
|
sendHtmlEmail(entity.getEmail(),entity.getSubject(),entity.getTemplateName(),entity.getData());
|
||||||
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(javaMailSender.createMimeMessage(),true);
|
|
||||||
//邮件发信人
|
|
||||||
mimeMessageHelper.setFrom(sendMailer);
|
|
||||||
//邮件收信人 1或多个
|
|
||||||
mimeMessageHelper.setTo(to.split(","));
|
|
||||||
//邮件主题
|
|
||||||
mimeMessageHelper.setSubject(subject);
|
|
||||||
//邮件内容 true 代表支持html
|
|
||||||
mimeMessageHelper.setText(content,true);
|
|
||||||
//邮件发送时间
|
|
||||||
mimeMessageHelper.setSentDate(new Date());
|
|
||||||
|
|
||||||
//发送邮件
|
|
||||||
javaMailSender.send(mimeMessageHelper.getMimeMessage());
|
|
||||||
System.out.println("发送邮件成功:"+sendMailer+"->"+to);
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
System.out.println("发送邮件失败:"+e.getMessage());
|
System.out.println("发送邮件失败:"+e.getMessage());
|
||||||
@@ -189,9 +212,13 @@ public class MaliServiceImpl implements MailService {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void sendCodeMailMessage(String to, String code) {
|
public void sendCodeMailMessage(String to, String code) {
|
||||||
String subject = "账号注册,邮箱验证码";
|
//String subject = "账号注册,邮箱验证码";
|
||||||
String text = "注册验证码10分钟内有效:\n\t"+code;
|
//String text = "注册验证码10分钟内有效:\n\t"+code;
|
||||||
sendTextMailMessage(to,subject,text);
|
Map<String, Object> content = new HashMap<>();
|
||||||
|
content.put("code",code);
|
||||||
|
content.put("text","The verification code for registration is valid for 10 minutes");
|
||||||
|
EmailTemplateEntity message = new EmailTemplateEntity(to,"Account registration, email verification code","emailCode-en",content);
|
||||||
|
sendHtmlMailMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -201,25 +228,39 @@ public class MaliServiceImpl implements MailService {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void sendLoginCodeMailMessage(String to, String code) {
|
public void sendLoginCodeMailMessage(String to, String code) {
|
||||||
String subject = "用户登录,邮箱验证码";
|
//String subject = "用户登录,邮箱验证码";
|
||||||
String text = "登录验证码10分钟内有效:\n\t"+code;
|
//String text = "登录验证码10分钟内有效:\n\t"+code;
|
||||||
sendTextMailMessage(to,subject,text);
|
Map<String, Object> content = new HashMap<>();
|
||||||
|
content.put("code",code);
|
||||||
|
content.put("text","Login verification code is valid within 10 minutes");
|
||||||
|
EmailTemplateEntity entity = new EmailTemplateEntity(to,"User login, email verification code","emailCode-en",content);
|
||||||
|
sendHtmlMailMessage(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendResetPwdMailMessage(String to, String code) {
|
public void sendResetPwdMailMessage(String to, String code) {
|
||||||
String subject = "账号重置密码,邮箱验证码";
|
//String subject = "账号重置密码,邮箱验证码";
|
||||||
String text = "您正在重置密码,如果不是您本人操作,请忽略。验证码10分钟内有效:\n\t"+code;
|
//String text = "您正在重置密码,如果不是您本人操作,请忽略。验证码10分钟内有效:\n\t"+code;
|
||||||
sendTextMailMessage(to,subject,text);
|
|
||||||
|
Map<String, Object> content = new HashMap<>();
|
||||||
|
content.put("code",code);
|
||||||
|
content.put("text","You are resetting your password. If this is not done by you, please ignore it. The verification code is valid for 10 minutes.");
|
||||||
|
EmailTemplateEntity entity = new EmailTemplateEntity(to,"Reset account password, email verification code","emailCode-en",content);
|
||||||
|
sendHtmlMailMessage(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendUpdatePwdMailMessage(String to, String code) {
|
public void sendUpdatePwdMailMessage(String to, String code) {
|
||||||
String subject = "修改密码,邮箱验证码";
|
//String subject = "修改密码,邮箱验证码";
|
||||||
String text = "您正在修改密码,如果不是您本人操作,请忽略。验证码10分钟内有效:\n\t"+code;
|
//String text = "您正在修改密码,如果不是您本人操作,请忽略。验证码10分钟内有效:\n\t"+code;
|
||||||
sendTextMailMessage(to,subject,text);
|
|
||||||
|
Map<String, Object> content = new HashMap<>();
|
||||||
|
content.put("code",code);
|
||||||
|
content.put("text","You are currently modifying your password. If this is not done by you, please ignore it. The verification code is valid for 10 minutes.");
|
||||||
|
EmailTemplateEntity entity = new EmailTemplateEntity(to,"Change password, email verification code","emailCode-en",content);
|
||||||
|
sendHtmlMailMessage(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
89
m2pool-auth/src/main/resources/bootstrap-dev.yml
Normal file
89
m2pool-auth/src/main/resources/bootstrap-dev.yml
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
server:
|
||||||
|
port: 7777
|
||||||
|
|
||||||
|
# Spring
|
||||||
|
spring:
|
||||||
|
#邮箱基本配置
|
||||||
|
mail:
|
||||||
|
# 配置在limit_time内,用户可以发送limit次验证码
|
||||||
|
limit: 2 这个是我额外的配置,结合邮箱服务用的
|
||||||
|
limitTime: 10 这个是我额外的配置
|
||||||
|
#配置smtp服务主机地址
|
||||||
|
# sina smtp.sina.cn
|
||||||
|
# aliyun smtp.aliyun.com
|
||||||
|
# 163 smtp.163.com 端口号465或994
|
||||||
|
host: mail.privateemail.com
|
||||||
|
#发送者邮箱
|
||||||
|
username: do.not.reply@m2pool.com
|
||||||
|
#配置密码,注意不是真正的密码,而是刚刚申请到的授权码
|
||||||
|
# password:
|
||||||
|
# password: M2202401!
|
||||||
|
# password: axvm-zfgx-cgcg-qhhu
|
||||||
|
password: M2202401!
|
||||||
|
|
||||||
|
#端口号
|
||||||
|
port: 587
|
||||||
|
# port: 465
|
||||||
|
#默认的邮件编码为UTF-8
|
||||||
|
default-encoding: UTF-8
|
||||||
|
#其他参数
|
||||||
|
properties:
|
||||||
|
mail:
|
||||||
|
#配置SSL 加密工厂
|
||||||
|
smtp:
|
||||||
|
ssl:
|
||||||
|
#本地测试,先放开ssl
|
||||||
|
enable: false
|
||||||
|
required: false
|
||||||
|
#开启debug模式,这样邮件发送过程的日志会在控制台打印出来,方便排查错误
|
||||||
|
debug: false
|
||||||
|
socketFactory:
|
||||||
|
class: javax.net.ssl.SSLSocketFactory
|
||||||
|
#
|
||||||
|
# host: smtp.qq.com
|
||||||
|
# #发送者邮箱
|
||||||
|
# username: 1328642438@qq.com
|
||||||
|
# #配置密码,注意不是真正的密码,而是刚刚申请到的授权码
|
||||||
|
# # password:
|
||||||
|
# # password: M2pool2024@!
|
||||||
|
# # password: axvm-zfgx-cgcg-qhhu
|
||||||
|
# password: eqrzqxeqzlshhedh
|
||||||
|
#
|
||||||
|
# #端口号
|
||||||
|
# port: 465
|
||||||
|
# #默认的邮件编码为UTF-8
|
||||||
|
# default-encoding: UTF-8
|
||||||
|
# #其他参数
|
||||||
|
# properties:
|
||||||
|
# mail:
|
||||||
|
# #配置SSL 加密工厂
|
||||||
|
# smtp:
|
||||||
|
# ssl:
|
||||||
|
# #本地测试,先放开ssl
|
||||||
|
# enable: true
|
||||||
|
# required: true
|
||||||
|
# #开启debug模式,这样邮件发送过程的日志会在控制台打印出来,方便排查错误
|
||||||
|
# debug: false
|
||||||
|
# socketFactory:
|
||||||
|
# class: javax.net.ssl.SSLSocketFactory
|
||||||
|
|
||||||
|
application:
|
||||||
|
# 应用名称
|
||||||
|
name: m2pool-auth
|
||||||
|
cloud:
|
||||||
|
nacos:
|
||||||
|
discovery:
|
||||||
|
# 服务注册地址
|
||||||
|
server-addr: 127.0.0.1:8848
|
||||||
|
namespace: m2_dev
|
||||||
|
group: m2_dev_group
|
||||||
|
config:
|
||||||
|
# 配置中心地址
|
||||||
|
server-addr: 127.0.0.1:8848
|
||||||
|
# 配置文件格式
|
||||||
|
file-extension: yml
|
||||||
|
# 共享配置
|
||||||
|
shared-configs:
|
||||||
|
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
|
||||||
|
namespace: m2_dev
|
||||||
|
group: m2_dev_group
|
||||||
@@ -62,3 +62,5 @@ spring:
|
|||||||
namespace: m2_prod
|
namespace: m2_prod
|
||||||
group: m2_prod_group
|
group: m2_prod_group
|
||||||
|
|
||||||
|
image:
|
||||||
|
prefix: https://m2pool.com
|
||||||
|
|||||||
@@ -87,3 +87,5 @@ spring:
|
|||||||
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
|
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
|
||||||
namespace: m2_test
|
namespace: m2_test
|
||||||
group: m2_test_group
|
group: m2_test_group
|
||||||
|
image:
|
||||||
|
prefix: https://test.m2pool.com
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
spring:
|
spring:
|
||||||
profiles:
|
profiles:
|
||||||
active: test
|
active: prod
|
||||||
|
|||||||
50
m2pool-auth/src/main/resources/templates/emailCode-en.html
Normal file
50
m2pool-auth/src/main/resources/templates/emailCode-en.html
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN" xmlns:th="http://www.w3.org/1999/xhtml">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Email code</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body style="margin:0; padding:0;">
|
||||||
|
<!-- 合并 th:style 属性 -->
|
||||||
|
<div class="container" role="region" aria-label="M2POOL Email verification code page" tabindex="0"
|
||||||
|
th:style="'background-image: url(' + @{${imagePrefix} + '/img/email/bg1.png'} + '); width:100%; max-width:600px; height:auto; min-height:100vh; margin:0 auto; box-sizing:border-box; padding:5%; position:relative; overflow:hidden; background-color:#f5f5f5; background-size:cover; background-repeat:no-repeat; '">
|
||||||
|
<!-- 顶部品牌标识 -->
|
||||||
|
<div class="brand" aria-label="M2POOL brand logo" style="width:100%;">
|
||||||
|
<img th:src= "@{${imagePrefix} + '/img/email/logo.png'}" alt="logo" style="width: 8vw; height: auto; margin-left: 10%; margin-top: 6%;">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 中心验证码卡片 -->
|
||||||
|
<!-- 合并 th:style 属性 -->
|
||||||
|
<section class="card" aria-label="Verification code card"
|
||||||
|
th:style="'background-image: url(' + @{${imagePrefix} + '/img/email/daio.png'} + '); width:100%; max-width:320px; height:auto; min-height:250px; margin:0 auto; margin-top:10vh; box-shadow:0 8px 24px rgba(17, 24, 39, 0.10), 0 2px 6px rgba(17, 24, 39, 0.06); position:relative; overflow:hidden; display:block; text-align:center; background-color:#ffffff; background-size:120% auto; background-position:center; background-repeat:no-repeat; border-radius:12px; padding:5%;'">
|
||||||
|
<!-- 合并 th:style 属性 -->
|
||||||
|
<p class="notice" th:text="${text}" style="color:rgba(0,0,0,0.7); font-size:18px; margin-top:10%; text-align:center;"></p>
|
||||||
|
<!-- 合并 th:style 属性 -->
|
||||||
|
<div class="code-box" aria-live="polite" aria-label="CAPTCHA"
|
||||||
|
style="position:relative; display:inline-flex; align-items:center; justify-content:center; margin-top:2vh; width:80%; max-width:300px; height:50px; border-radius:12px; background:#ffffff; border:3px solid #651EFE;">
|
||||||
|
<!-- 合并 th:style 属性 -->
|
||||||
|
<span class="code-text js-code-text" data-default-code="4MKM6AX" th:text="${code}"
|
||||||
|
style="font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace; font-weight:800; font-size:24px; letter-spacing:0.18em; color:#111827;"></span>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- 底部帮助与联系入口 -->
|
||||||
|
<footer class="page-footer" style="margin-top:18vh; width:100%; height:auto; text-align:center;">
|
||||||
|
<!-- 合并 th:style 属性 -->
|
||||||
|
<div class="divider" aria-hidden="true"
|
||||||
|
style="width:100%; height:3px; background:#DDDDDD; margin:8px 0 20px;"></div>
|
||||||
|
<!-- 合并 th:style 属性 -->
|
||||||
|
<p style="margin:0; padding:0; font-size:14px; color:#777777;">
|
||||||
|
Thank you for choosing M2POOL. Need help?
|
||||||
|
<a class="contact-link" href="mailto:support@m2pool.com" aria-label="Contact customer service email"
|
||||||
|
style="color:#111827; font-weight:800; text-decoration:none; border-bottom:2px solid #111827; outline:none;">Please
|
||||||
|
contact customer service.</a>
|
||||||
|
</p>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN" xmlns:th="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>offline notification</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container" role="region" aria-label="M2POOL offline notification" tabindex="0"
|
||||||
|
th:style="'background-image: url(' + @{${imagePrefix} + '/img/email/bg1.png'} + '); width:100%; max-width:600px; height:auto; min-height:100vh; margin:0 auto; position:relative; overflow:hidden; padding:2%; background-color:#f5f5f5; background-size:cover; background-repeat:no-repeat;box-sizing:border-box;'">
|
||||||
|
<!-- 顶部品牌标识 -->
|
||||||
|
<div class="brand" aria-label="M2POOL brand logo">
|
||||||
|
<img th:src= "@{${imagePrefix} + '/img/email/logo.png'}" alt="logo" style="width:120px; height:auto; margin-left:10%; margin-top:6%;">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 中心验证码卡片 -->
|
||||||
|
<section class="card" aria-label="Offline Notification Card" th:style="'background-image: url(' + @{${imagePrefix} + '/img/email/daio.png'} + ');width:100%; max-width:310px; height:auto; min-height:240px; margin:0 auto; margin-top:10vh; box-shadow:0 8px 24px rgba(17, 24, 39, 0.10), 0 2px 6px rgba(17, 24, 39, 0.06); position:relative; overflow:hidden; padding:44px 40px 36px; text-align:center; background-color:#ffffff; background-size:105% 112%; background-position:center; background-repeat:no-repeat; border-radius:12px;'">
|
||||||
|
<p class="notice" style="color:rgba(0,0,0,0.8); font-size:18px; margin-bottom:15px;">Your <span class="account-name" th:text="${coin}" style="color:#F94D87; font-weight:900; font-size:20px;"></span> mining account: <span class="account-name" style="color:#F94D87; font-weight:900; font-size:20px;" th:text="${user}"></span> </p>
|
||||||
|
<p class="notice" style="color:rgba(0,0,0,0.8); font-size:18px; margin-bottom:15px;"> <span class="account-name" th:text="${offOnlineNumbers}" style="color:#F94D87; font-weight:900; font-size:20px;"></span> mining machines are offline!</p>
|
||||||
|
<p class="notice" style="color:rgba(0,0,0,0.8); font-size:18px;">If your mining rig has been abnormally disconnected, please address it promptly!</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- 底部帮助与联系入口 -->
|
||||||
|
<footer class="page-footer" style="margin-top:18vh; width:100%; height:auto; text-align:center;">
|
||||||
|
<div class="divider" aria-hidden="true" style="width:100%; height:3px; background:#DDDDDD; margin:8px 0 20px;"></div>
|
||||||
|
<p style="margin:0; padding:0; font-size:14px; color:#777777;">
|
||||||
|
Thank you for choosing M2POOL. Need help?
|
||||||
|
<a class="contact-link" style="color:#111827; font-weight:800; text-decoration:none; border-bottom:2px solid #111827; outline:none;" href="mailto:support@m2pool.com" aria-label="Contact Customer Service Email">Please contact customer service.</a>
|
||||||
|
</p>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -126,8 +126,6 @@
|
|||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-mail</artifactId>
|
<artifactId>spring-boot-starter-mail</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -320,4 +320,46 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
|
|||||||
return DateUtils.parseDate(format);
|
return DateUtils.parseDate(format);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前时间前一个包含 30 分或整点的 30 分钟时间段起始时间
|
||||||
|
* @param date 输入的日期
|
||||||
|
* @return 前一个 30 分或整点时间段起始的日期
|
||||||
|
*/
|
||||||
|
public static Date getPreviousHalfHourOrFullHour(Date date) {
|
||||||
|
Calendar calendar = Calendar.getInstance();
|
||||||
|
calendar.setTime(date);
|
||||||
|
|
||||||
|
int minute = calendar.get(Calendar.MINUTE);
|
||||||
|
// 如果当前分钟数小于 30,前一个时间段起始是上一个整点
|
||||||
|
if (minute < 30) {
|
||||||
|
calendar.set(Calendar.MINUTE, 0);
|
||||||
|
} else {
|
||||||
|
// 如果当前分钟数大于等于 30,前一个时间段起始是 30 分
|
||||||
|
calendar.set(Calendar.MINUTE, 30);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将秒和毫秒置为 0
|
||||||
|
calendar.set(Calendar.SECOND, 0);
|
||||||
|
calendar.set(Calendar.MILLISECOND, 0);
|
||||||
|
|
||||||
|
// 如果当前分钟已经是 0 分或者 30 分,需要再往前推 30 分钟
|
||||||
|
if (minute == 0 || minute == 30) {
|
||||||
|
calendar.add(Calendar.MINUTE, -30);
|
||||||
|
}
|
||||||
|
|
||||||
|
return calendar.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取指定日期一个月前的时间
|
||||||
|
* @param date 输入的日期
|
||||||
|
* @return 一个月前的日期
|
||||||
|
*/
|
||||||
|
public static Date getOneMonthAgo(Date date) {
|
||||||
|
Calendar calendar = Calendar.getInstance();
|
||||||
|
calendar.setTime(date);
|
||||||
|
calendar.add(Calendar.DAY_OF_MONTH, -30);
|
||||||
|
return calendar.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ public class MimeTypeUtils
|
|||||||
"rar", "zip", "gz", "bz2",
|
"rar", "zip", "gz", "bz2",
|
||||||
// 视频格式
|
// 视频格式
|
||||||
"mp4", "avi", "rmvb",
|
"mp4", "avi", "rmvb",
|
||||||
|
//音频格式
|
||||||
|
"mp3","aif","aiff","wav","wma",
|
||||||
// pdf
|
// pdf
|
||||||
"pdf" };
|
"pdf" };
|
||||||
|
|
||||||
|
|||||||
@@ -263,4 +263,4 @@ public class IpUtils
|
|||||||
{
|
{
|
||||||
return StringUtils.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString);
|
return StringUtils.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import org.springframework.data.redis.core.RedisTemplate;
|
|||||||
import org.springframework.data.redis.core.ValueOperations;
|
import org.springframework.data.redis.core.ValueOperations;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@@ -117,6 +118,31 @@ public class RedisService {
|
|||||||
return operation.get(key);
|
return operation.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 所有数字类型转换为BigDecimal
|
||||||
|
* @param key 缓存键值
|
||||||
|
* @return 缓存键值对应数据
|
||||||
|
*/
|
||||||
|
public BigDecimal getCacheBigDecimal(final String key) {
|
||||||
|
ValueOperations<String, Object> operation = redisTemplate.opsForValue();
|
||||||
|
Object value = operation.get(key);
|
||||||
|
if (value != null) {
|
||||||
|
if (value instanceof BigDecimal) {
|
||||||
|
return (BigDecimal) value;
|
||||||
|
} else if (value instanceof String) {
|
||||||
|
try {
|
||||||
|
return new BigDecimal((String) value);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
// 处理字符串无法转换为 BigDecimal 的情况
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else if (value instanceof Number) {
|
||||||
|
return new BigDecimal(value.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除单个对象
|
* 删除单个对象
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -215,6 +215,7 @@ public class AuthLogic {
|
|||||||
{
|
{
|
||||||
if (requiresRoles.logical() == Logical.AND)
|
if (requiresRoles.logical() == Logical.AND)
|
||||||
{
|
{
|
||||||
|
|
||||||
checkRoleAnd(requiresRoles.value());
|
checkRoleAnd(requiresRoles.value());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -248,6 +249,8 @@ public class AuthLogic {
|
|||||||
public void checkRoleOr(String... roles)
|
public void checkRoleOr(String... roles)
|
||||||
{
|
{
|
||||||
Set<String> roleList = getRoleList();
|
Set<String> roleList = getRoleList();
|
||||||
|
System.out.println("从token获取的role"+roleList +"需要的权限"+roles);
|
||||||
|
|
||||||
for (String role : roles)
|
for (String role : roles)
|
||||||
{
|
{
|
||||||
if (hasRole(roleList, role))
|
if (hasRole(roleList, role))
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.m2pool.common.security.config;
|
package com.m2pool.common.security.config;
|
||||||
|
|
||||||
|
import com.m2pool.common.security.interceptor.CoinInterceptor;
|
||||||
import com.m2pool.common.security.interceptor.HeaderInterceptor;
|
import com.m2pool.common.security.interceptor.HeaderInterceptor;
|
||||||
import com.m2pool.common.security.interceptor.OpenApiHeaderInterceptor;
|
import com.m2pool.common.security.interceptor.OpenApiHeaderInterceptor;
|
||||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||||
@@ -25,7 +26,6 @@ public class WebMvcConfig implements WebMvcConfigurer {
|
|||||||
"/miner/hashrate_real","/miner/hashrate_history","/miner/hashrate_last24h",
|
"/miner/hashrate_real","/miner/hashrate_history","/miner/hashrate_last24h",
|
||||||
"/pool/hashrate","/pool/hashrate_history","/pool/miners_list","/pool/watch","/oapi/**"};
|
"/pool/hashrate","/pool/hashrate_history","/pool/miners_list","/pool/watch","/oapi/**"};
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addInterceptors(InterceptorRegistry registry) {
|
public void addInterceptors(InterceptorRegistry registry) {
|
||||||
registry.addInterceptor(getHeaderInterceptor())
|
registry.addInterceptor(getHeaderInterceptor())
|
||||||
@@ -34,9 +34,14 @@ public class WebMvcConfig implements WebMvcConfigurer {
|
|||||||
.order(-10);
|
.order(-10);
|
||||||
|
|
||||||
registry.addInterceptor(getOpenApiHeaderInterceptor())
|
registry.addInterceptor(getOpenApiHeaderInterceptor())
|
||||||
.addPathPatterns(matchUrls).
|
.addPathPatterns(matchUrls)
|
||||||
excludePathPatterns("/auth/**,/system/**,/pool/**")
|
.excludePathPatterns("/auth/**,/system/**,/pool/**")
|
||||||
.order(-15);
|
.order(-15);
|
||||||
|
|
||||||
|
//registry.addInterceptor(getCoinInterceptor())
|
||||||
|
// .addPathPatterns("/**")
|
||||||
|
// .order(-20);
|
||||||
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 自定义请求头拦截器
|
* 自定义请求头拦截器
|
||||||
@@ -45,4 +50,5 @@ public class WebMvcConfig implements WebMvcConfigurer {
|
|||||||
|
|
||||||
public OpenApiHeaderInterceptor getOpenApiHeaderInterceptor(){return new OpenApiHeaderInterceptor();}
|
public OpenApiHeaderInterceptor getOpenApiHeaderInterceptor(){return new OpenApiHeaderInterceptor();}
|
||||||
|
|
||||||
|
public CoinInterceptor getCoinInterceptor(){return new CoinInterceptor();}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.m2pool.common.security.interceptor;
|
|||||||
|
|
||||||
import com.m2pool.common.core.constant.SecurityConstants;
|
import com.m2pool.common.core.constant.SecurityConstants;
|
||||||
import com.m2pool.common.core.context.SecurityContextHolder;
|
import com.m2pool.common.core.context.SecurityContextHolder;
|
||||||
|
import com.m2pool.common.core.utils.JwtUtils;
|
||||||
import com.m2pool.common.core.utils.ServletUtils;
|
import com.m2pool.common.core.utils.ServletUtils;
|
||||||
import com.m2pool.common.core.utils.StringUtils;
|
import com.m2pool.common.core.utils.StringUtils;
|
||||||
import com.m2pool.common.core.utils.ip.IpUtils;
|
import com.m2pool.common.core.utils.ip.IpUtils;
|
||||||
@@ -37,6 +38,11 @@ public class HeaderInterceptor implements AsyncHandlerInterceptor {
|
|||||||
SecurityContextHolder.setUserName(ServletUtils.getHeader(request,SecurityConstants.DETAILS_USERNAME));
|
SecurityContextHolder.setUserName(ServletUtils.getHeader(request,SecurityConstants.DETAILS_USERNAME));
|
||||||
SecurityContextHolder.setUserKey(ServletUtils.getHeader(request,SecurityConstants.USER_KEY));
|
SecurityContextHolder.setUserKey(ServletUtils.getHeader(request,SecurityConstants.USER_KEY));
|
||||||
|
|
||||||
|
//开发环境
|
||||||
|
String authorization = request.getHeader("Authorization");
|
||||||
|
String userName = JwtUtils.getUserName(authorization);
|
||||||
|
SecurityContextHolder.setUserName(userName);
|
||||||
|
|
||||||
String token = SecurityUtils.getToken();
|
String token = SecurityUtils.getToken();
|
||||||
if(StringUtils.isNotEmpty(token)){
|
if(StringUtils.isNotEmpty(token)){
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
|||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.Profile;
|
||||||
import springfox.documentation.builders.ApiInfoBuilder;
|
import springfox.documentation.builders.ApiInfoBuilder;
|
||||||
import springfox.documentation.builders.PathSelectors;
|
import springfox.documentation.builders.PathSelectors;
|
||||||
import springfox.documentation.builders.RequestHandlerSelectors;
|
import springfox.documentation.builders.RequestHandlerSelectors;
|
||||||
|
|||||||
@@ -118,11 +118,6 @@
|
|||||||
<artifactId>common-core</artifactId>
|
<artifactId>common-core</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.github.xiaoymin</groupId>
|
|
||||||
<artifactId>knife4j-spring-boot-starter</artifactId>
|
|
||||||
<version>3.0.3</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
server:
|
server:
|
||||||
port: 8101
|
port: 8101
|
||||||
# Spring
|
# Spring
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
spring:
|
spring:
|
||||||
profiles:
|
profiles:
|
||||||
active: test
|
active: prod
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import com.m2pool.chat.coverter.CommonMessageConvert;
|
|||||||
import com.m2pool.chat.interceptor.WebsocketChannelInterceptor;
|
import com.m2pool.chat.interceptor.WebsocketChannelInterceptor;
|
||||||
import com.m2pool.chat.interceptor.WebsocketHandshakeInterceptor;
|
import com.m2pool.chat.interceptor.WebsocketHandshakeInterceptor;
|
||||||
import org.springframework.context.ApplicationEventPublisher;
|
import org.springframework.context.ApplicationEventPublisher;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.messaging.converter.MessageConverter;
|
import org.springframework.messaging.converter.MessageConverter;
|
||||||
import org.springframework.messaging.simp.config.ChannelRegistration;
|
import org.springframework.messaging.simp.config.ChannelRegistration;
|
||||||
@@ -14,6 +15,8 @@ import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBr
|
|||||||
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
|
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
|
||||||
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
|
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
|
||||||
import org.springframework.web.socket.config.annotation.WebSocketTransportRegistration;
|
import org.springframework.web.socket.config.annotation.WebSocketTransportRegistration;
|
||||||
|
import org.springframework.web.socket.messaging.StompSubProtocolHandler;
|
||||||
|
import org.springframework.web.socket.messaging.SubProtocolWebSocketHandler;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -55,6 +58,7 @@ public class WebSocketBrokerConfig implements WebSocketMessageBrokerConfigurer {
|
|||||||
.setAllowedOrigins("*");
|
.setAllowedOrigins("*");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 配置消息代理
|
* 配置消息代理
|
||||||
* 客户端订阅消息的请求前缀,topic用于广播推送,queue用于点对点推送
|
* 客户端订阅消息的请求前缀,topic用于广播推送,queue用于点对点推送
|
||||||
@@ -63,12 +67,13 @@ public class WebSocketBrokerConfig implements WebSocketMessageBrokerConfigurer {
|
|||||||
@Override
|
@Override
|
||||||
public void configureMessageBroker(MessageBrokerRegistry config) {
|
public void configureMessageBroker(MessageBrokerRegistry config) {
|
||||||
|
|
||||||
config.enableSimpleBroker(Destination.TOPIC, Destination.QUEUE)
|
config.enableSimpleBroker(Destination.TOPIC, Destination.QUEUE_USER,Destination.QUEUE_CUSTOMER,Destination.QUEUE_CLOSE_ROOM)
|
||||||
.setHeartbeatValue(new long[] {10000, 10000})
|
.setHeartbeatValue(new long[] {30000, 30000})
|
||||||
.setTaskScheduler(new DefaultManagedTaskScheduler());
|
.setTaskScheduler(new DefaultManagedTaskScheduler());
|
||||||
|
|
||||||
|
//发送消息前缀
|
||||||
config.setApplicationDestinationPrefixes(Destination.SEND_PREFIX);
|
config.setApplicationDestinationPrefixes(Destination.SEND_PREFIX);
|
||||||
//服务端通知客户端的前缀,可以不设置,默认为user
|
//客户端订阅前缀,可以不设置,默认为user
|
||||||
config.setUserDestinationPrefix(Destination.USER_PREFIX);
|
config.setUserDestinationPrefix(Destination.USER_PREFIX);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,12 +87,23 @@ public class WebSocketBrokerConfig implements WebSocketMessageBrokerConfigurer {
|
|||||||
registration
|
registration
|
||||||
.setMessageSizeLimit(customWebSocketConfig.getMessageSizeLimit())
|
.setMessageSizeLimit(customWebSocketConfig.getMessageSizeLimit())
|
||||||
.setSendTimeLimit(customWebSocketConfig.getSendTimeLimit())
|
.setSendTimeLimit(customWebSocketConfig.getSendTimeLimit())
|
||||||
.setSendBufferSizeLimit(customWebSocketConfig.getSendBufferSizeLimit())
|
.setSendBufferSizeLimit(customWebSocketConfig.getSendBufferSizeLimit());
|
||||||
// 首次连接超时时间.正常情况下,前端订阅 和 心跳包的影响 不会超时断连
|
// 首次连接超时时间.正常情况下,前端订阅 和 心跳包的影响 不会超时断连
|
||||||
.setTimeToFirstMessage(customWebSocketConfig.getTimeToFirstMessage());
|
// .setTimeToFirstMessage(customWebSocketConfig.getTimeToFirstMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// @Bean
|
||||||
|
// public ServletServerContainerFactoryBean createServletServerContainerFactoryBean() {
|
||||||
|
// ServletServerContainerFactoryBean factoryBean = new ServletServerContainerFactoryBean();
|
||||||
|
// factoryBean.setMaxTextMessageBufferSize(customWebSocketConfig.getMessageSizeLimit());
|
||||||
|
// factoryBean.setMaxBinaryMessageBufferSize(customWebSocketConfig.getMessageSizeLimit());
|
||||||
|
// factoryBean.setMaxSessionIdleTimeout(2048L * 2048L);
|
||||||
|
// factoryBean.setAsyncSendTimeout(2048L * 2048L);
|
||||||
|
// return factoryBean;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 配置客户端出站通道拦截器(默认线程1)
|
* 配置客户端出站通道拦截器(默认线程1)
|
||||||
@@ -114,4 +130,5 @@ public class WebSocketBrokerConfig implements WebSocketMessageBrokerConfigurer {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,15 +7,25 @@ package com.m2pool.chat.constant;
|
|||||||
* @Date 2025/4/14 14:54
|
* @Date 2025/4/14 14:54
|
||||||
*/
|
*/
|
||||||
public class Destination {
|
public class Destination {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* stomp 默认单对单 发送目的地.单对单消息默认 /
|
* stomp 默认单对单 发送目的地.单对单消息默认 /
|
||||||
*/
|
*/
|
||||||
public static final String QUEUE = "/queue";
|
public static final String QUEUE = "/queue";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* stomp 默认单对单 发送目的地.单对单消息默认 /
|
||||||
|
*/
|
||||||
|
public static final String QUEUE_USER = "/queue/user";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* stomp 默认单对单 发送目的地.单对单消息默认 /
|
||||||
|
*/
|
||||||
|
public static final String QUEUE_CUSTOMER = "/queue/customer";
|
||||||
/**
|
/**
|
||||||
* 聊天室关闭 路径
|
* 聊天室关闭 路径
|
||||||
*/
|
*/
|
||||||
public static final String QUEUE_CLOSE_ROOM = "/close/room/";
|
public static final String QUEUE_CLOSE_ROOM = "/queue/close/room/";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* stomp 默认群发 目的地
|
* stomp 默认群发 目的地
|
||||||
@@ -23,9 +33,9 @@ public class Destination {
|
|||||||
public static final String TOPIC = "/topic";
|
public static final String TOPIC = "/topic";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 前端订阅消息所需前缀。 stomp 默认user前缀。
|
* 前端订阅消息所需前缀point。 stomp 默认user前缀。
|
||||||
*/
|
*/
|
||||||
public static final String USER_PREFIX = "/user";
|
public static final String USER_PREFIX = "/sub";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* stomp 默认发送消息前缀。
|
* stomp 默认发送消息前缀。
|
||||||
|
|||||||
@@ -10,12 +10,14 @@ import lombok.Getter;
|
|||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
public enum ExceptionEnum {
|
public enum ExceptionEnum {
|
||||||
IP_LIMIT_CONNECT(1020, "本机连接数已达上限,请关闭已有链接"),
|
IP_LIMIT_CONNECT(1020, "本机连接数已达上限9,请先关闭已有链接,再重新链接"),
|
||||||
MAX_LIMIT_CONNECT(1021, "服务器websocket连接数已达上限,服务器拒绝链接"),
|
MAX_LIMIT_CONNECT(1021, "服务器websocket连接数已达上限,服务器拒绝链接"),
|
||||||
SET_PRINCIPAL_FAIL(1022, "websocket链接异常,用户身份设置失败"),
|
SET_PRINCIPAL_FAIL(1022, "websocket链接异常,用户身份设置失败"),
|
||||||
GET_PRINCIPAL_FAIL(1023, "websocket链接异常,用户信息邮箱获取失败"),
|
GET_PRINCIPAL_FAIL(1023, "websocket链接异常,用户信息邮箱获取失败"),
|
||||||
ACCOUNT_HAS_CONNECTED(1024, "当前登录用户在其他地方链接"),
|
ACCOUNT_HAS_CONNECTED(1024, "当前登录用户在其他地方链接"),
|
||||||
;
|
|
||||||
|
ROOM_NOT_EXIST(1025, "聊天室不存在,发送消息失败");
|
||||||
|
|
||||||
|
|
||||||
private final int code;
|
private final int code;
|
||||||
private final String description;
|
private final String description;
|
||||||
|
|||||||
@@ -52,8 +52,7 @@ public class ChatMessageController {
|
|||||||
|
|
||||||
@PostMapping("/read/message")
|
@PostMapping("/read/message")
|
||||||
@ApiOperation(value = "聊天室消息改已读")
|
@ApiOperation(value = "聊天室消息改已读")
|
||||||
@RequiresLogin
|
|
||||||
public R<String> readMessage(@RequestBody MessagePageVo pageVo) {
|
public R<String> readMessage(@RequestBody MessagePageVo pageVo) {
|
||||||
return chatMessageService.readMessage(pageVo.getRoomId(),pageVo.getUserType());
|
return chatMessageService.readMessage(pageVo.getRoomId(),pageVo.getUserType());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,4 +49,4 @@ public class ChatRoomController {
|
|||||||
public R<String> updateRoom(@RequestBody CharRoomVo charRoomVo) {
|
public R<String> updateRoom(@RequestBody CharRoomVo charRoomVo) {
|
||||||
return chatRoomService.updateRoom(charRoomVo);
|
return chatRoomService.updateRoom(charRoomVo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,13 +27,25 @@ public class StompController extends BaseController {
|
|||||||
private StompService stompService;
|
private StompService stompService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发送消息到对应的用户
|
* 发送消息给普通用户和游客
|
||||||
* @param userMessageVo 消息体
|
* @param userMessageVo 消息体
|
||||||
* @return 返回值通过CommonMessageConvert消息转换器转换
|
* @return 返回值通过CommonMessageConvert消息转换器转换
|
||||||
*/
|
*/
|
||||||
@MessageMapping("/send/message")
|
@MessageMapping("/send/message/to/user")
|
||||||
@SendToUser("/queue")
|
@SendToUser("/queue/user")
|
||||||
public AjaxResult sendMessageToUser(StompPrincipal principal, @Payload UserMessageVo userMessageVo) {
|
public AjaxResult sendMessageToUser(StompPrincipal principal, @Payload UserMessageVo userMessageVo) {
|
||||||
return stompService.sendMessageToUser(principal,userMessageVo);
|
return stompService.sendMessageToUser(principal,userMessageVo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送消息到对应的客服
|
||||||
|
* @param userMessageVo 消息体
|
||||||
|
* @return 返回值通过CommonMessageConvert消息转换器转换
|
||||||
|
*/
|
||||||
|
@MessageMapping("/send/message/to/customer")
|
||||||
|
@SendToUser("/queue/customer/")
|
||||||
|
public AjaxResult sendMessageToCustomer(StompPrincipal principal, @Payload UserMessageVo userMessageVo) {
|
||||||
|
return stompService.sendMessageToCustomer(principal,userMessageVo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ public class CommonMessageConvert implements MessageConverter {
|
|||||||
/**
|
/**
|
||||||
* 将客户端发送过来的消息转换为指定的对象
|
* 将客户端发送过来的消息转换为指定的对象
|
||||||
* @param message 客户端发送过来的消息
|
* @param message 客户端发送过来的消息
|
||||||
* @param targetClass 目标数据类型
|
* @param targetClass 目标数据类型 注意:这里的targetClass是消息对象,对应接口的@Payload 注解的类型,且里面序列化的字段必须一模一样。否则序列化报错
|
||||||
* @return 转换后的对象
|
* @return 转换后的对象
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@@ -27,8 +27,10 @@ public class CommonMessageConvert implements MessageConverter {
|
|||||||
if (message.getPayload() instanceof byte[]) {
|
if (message.getPayload() instanceof byte[]) {
|
||||||
try {
|
try {
|
||||||
String textPayload = new String((byte[]) message.getPayload(), StandardCharsets.UTF_8);
|
String textPayload = new String((byte[]) message.getPayload(), StandardCharsets.UTF_8);
|
||||||
|
System.out.println("发送者发送到服务器的消息:"+textPayload);
|
||||||
return JsonUtil.convertString2Object(textPayload,targetClass);
|
return JsonUtil.convertString2Object(textPayload,targetClass);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
System.out.println("错误详情"+e);
|
||||||
throw new MessageDeliveryException( "消息格式错误");
|
throw new MessageDeliveryException( "消息格式错误");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -46,8 +48,8 @@ public class CommonMessageConvert implements MessageConverter {
|
|||||||
@Override
|
@Override
|
||||||
public Message<?> toMessage(Object payload, MessageHeaders headers) {
|
public Message<?> toMessage(Object payload, MessageHeaders headers) {
|
||||||
String str = JsonUtil.toJson(payload);
|
String str = JsonUtil.toJson(payload);
|
||||||
|
System.out.println("发送给接受者的消息:"+payload);
|
||||||
byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
|
byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
|
||||||
System.out.println("发送给前端的消息"+new GenericMessage<>(bytes, headers));
|
|
||||||
return new GenericMessage<>(bytes, headers);
|
return new GenericMessage<>(bytes, headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ public class ChatRoomDto {
|
|||||||
* 聊天室id
|
* 聊天室id
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "聊天室id", example = "1")
|
@ApiModelProperty(value = "聊天室id", example = "1")
|
||||||
private String id;
|
private Long id;
|
||||||
/**
|
/**
|
||||||
* 聊天对象id:一般为客服
|
* 聊天对象id:一般为客服
|
||||||
*/
|
*/
|
||||||
@@ -62,4 +62,7 @@ public class ChatRoomDto {
|
|||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "聊天发起者id :一般为游客或登录用户", example = "1")
|
@ApiModelProperty(value = "聊天发起者id :一般为游客或登录用户", example = "1")
|
||||||
private String selfEmail;
|
private String selfEmail;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "客服是否在线", example = "true")
|
||||||
|
private boolean customerIsOnline;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ public class WebsocketMessageDto {
|
|||||||
/**
|
/**
|
||||||
* 聊天室id
|
* 聊天室id
|
||||||
*/
|
*/
|
||||||
private String roomId;
|
private Long roomId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否创建新聊天室
|
* 是否创建新聊天室
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ package com.m2pool.chat.interceptor;
|
|||||||
import com.m2pool.chat.config.CustomWebSocketConfig;
|
import com.m2pool.chat.config.CustomWebSocketConfig;
|
||||||
import com.m2pool.chat.constant.ExceptionEnum;
|
import com.m2pool.chat.constant.ExceptionEnum;
|
||||||
import com.m2pool.chat.entity.StompPrincipal;
|
import com.m2pool.chat.entity.StompPrincipal;
|
||||||
|
import com.m2pool.chat.listener.IpLimitEvent;
|
||||||
|
import io.lettuce.core.ScriptOutputType;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -18,7 +20,10 @@ import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
|
|||||||
import org.springframework.messaging.support.ChannelInterceptor;
|
import org.springframework.messaging.support.ChannelInterceptor;
|
||||||
import org.springframework.messaging.support.MessageHeaderAccessor;
|
import org.springframework.messaging.support.MessageHeaderAccessor;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
@@ -39,9 +44,9 @@ public class WebsocketChannelInterceptor implements ChannelInterceptor {
|
|||||||
private static final Logger LOGGER = LoggerFactory.getLogger(WebsocketChannelInterceptor.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(WebsocketChannelInterceptor.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 当前加入链接的ip ,key 为 ip ,VALUE 为用户邮箱
|
* 当前加入链接的ip ,key 为 ip+邮箱 ,VALUE 邮箱
|
||||||
*/
|
*/
|
||||||
private static final ConcurrentHashMap<String,String> ipConnectionCountMap = new ConcurrentHashMap<>();
|
private static final ConcurrentHashMap<String, EmailLimit> ipConnectionCountMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 当前链接数
|
* 当前链接数
|
||||||
@@ -73,6 +78,7 @@ public class WebsocketChannelInterceptor implements ChannelInterceptor {
|
|||||||
//获取链接建立时的请求头信息
|
//获取链接建立时的请求头信息
|
||||||
StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
|
StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
|
||||||
if (accessor.getCommand() == StompCommand.CONNECT ) {
|
if (accessor.getCommand() == StompCommand.CONNECT ) {
|
||||||
|
System.out.println("yyb-开始链接"+new Date());
|
||||||
StompHeaderAccessor mha = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
|
StompHeaderAccessor mha = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
|
||||||
if(mha == null){
|
if(mha == null){
|
||||||
throw new MessageDeliveryException(ExceptionEnum.fromCode(ExceptionEnum.SET_PRINCIPAL_FAIL));
|
throw new MessageDeliveryException(ExceptionEnum.fromCode(ExceptionEnum.SET_PRINCIPAL_FAIL));
|
||||||
@@ -84,9 +90,9 @@ public class WebsocketChannelInterceptor implements ChannelInterceptor {
|
|||||||
maxConnectionsLimit();
|
maxConnectionsLimit();
|
||||||
//根据客服端ip + 用户类型限制连接数
|
//根据客服端ip + 用户类型限制连接数
|
||||||
ipLimit(accessor,type,email);
|
ipLimit(accessor,type,email);
|
||||||
|
|
||||||
//链接请求头中用户信息存入stomp中
|
//链接请求头中用户信息存入stomp中
|
||||||
mha.setUser(new StompPrincipal(email,type,true));
|
mha.setUser(new StompPrincipal(email,type,true));
|
||||||
|
System.out.println("yyb-链接成功"+new Date());
|
||||||
}
|
}
|
||||||
if (accessor.getCommand() == StompCommand.SUBSCRIBE) {
|
if (accessor.getCommand() == StompCommand.SUBSCRIBE) {
|
||||||
LOGGER.info("------------websocket subscribe message");
|
LOGGER.info("------------websocket subscribe message");
|
||||||
@@ -97,7 +103,21 @@ public class WebsocketChannelInterceptor implements ChannelInterceptor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (accessor.getCommand() == StompCommand.DISCONNECT){
|
if (accessor.getCommand() == StompCommand.DISCONNECT){
|
||||||
disconnectHandler(accessor);
|
StompHeaderAccessor mha = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
|
||||||
|
if(mha == null){
|
||||||
|
try {
|
||||||
|
throw new MessageDeliveryException(ExceptionEnum.fromCode(ExceptionEnum.SET_PRINCIPAL_FAIL));
|
||||||
|
}catch (MessageDeliveryException e){
|
||||||
|
System.out.println("错误消息"+e.getMessage());
|
||||||
|
accessor.setHeader("error", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (mha.getUser() != null){
|
||||||
|
String email = mha.getUser().getName();
|
||||||
|
LOGGER.info("断开连接的邮箱为:{}",email);
|
||||||
|
disconnectHandler(accessor,email);
|
||||||
|
}
|
||||||
LOGGER.info("------------websocket disconnect");
|
LOGGER.info("------------websocket disconnect");
|
||||||
}
|
}
|
||||||
return message;
|
return message;
|
||||||
@@ -121,26 +141,32 @@ public class WebsocketChannelInterceptor implements ChannelInterceptor {
|
|||||||
Map<String, Object> sessionAttributes = accessor.getSessionAttributes();
|
Map<String, Object> sessionAttributes = accessor.getSessionAttributes();
|
||||||
if (sessionAttributes != null) {
|
if (sessionAttributes != null) {
|
||||||
String ipAddr = (String) sessionAttributes.get(IPADDR);
|
String ipAddr = (String) sessionAttributes.get(IPADDR);
|
||||||
String hasConnectionEmail = ipConnectionCountMap.get(ipAddr);
|
String key = ipAddr + email;
|
||||||
|
EmailLimit emailAndCount = ipConnectionCountMap.get(key);
|
||||||
|
|
||||||
//两种ip限制情况
|
//两种ip限制情况
|
||||||
//本次链接为游客 且ip上已经有人链接直接拒绝本次链接
|
//本次链接为游客 且ip上已经有人链接直接拒绝本次链接
|
||||||
if(type == TOURIST && hasConnectionEmail != null){
|
if(type == TOURIST && emailAndCount != null){
|
||||||
throw new MessageDeliveryException(ExceptionEnum.fromCode(ExceptionEnum.IP_LIMIT_CONNECT));
|
throw new MessageDeliveryException(ExceptionEnum.fromCode(ExceptionEnum.IP_LIMIT_CONNECT));
|
||||||
}
|
}
|
||||||
//本次链接为登录用户,并且已经链接.直接拒绝本次链接(多用户登录)
|
|
||||||
if ( type == LOGIN_USER ) {
|
// 登录用户现在ip限制不用做了,前端在同一ip情况下,不同用户会断开连接
|
||||||
if(email.equals(hasConnectionEmail) ){
|
//本次链接为登录用户,并且已经链接.直接拒绝本次链接
|
||||||
// StompPrincipal principal = new StompPrincipal(email, type, true);
|
if ( type != TOURIST && emailAndCount != null) {
|
||||||
// applicationEventPublisher.publishEvent(new IpLimitEvent(this, principal));
|
emailAndCount.setCount(emailAndCount.getCount() + 1);
|
||||||
|
if (emailAndCount.getCount() >= 10){
|
||||||
throw new MessageDeliveryException(ExceptionEnum.fromCode(ExceptionEnum.IP_LIMIT_CONNECT));
|
throw new MessageDeliveryException(ExceptionEnum.fromCode(ExceptionEnum.IP_LIMIT_CONNECT));
|
||||||
}
|
}
|
||||||
if(ipConnectionCountMap.containsValue(email)){
|
//if(ipConnectionCountMap.containsValue(emailAndCount)){
|
||||||
throw new MessageDeliveryException(ExceptionEnum.fromCode(ExceptionEnum.ACCOUNT_HAS_CONNECTED));
|
// ipConnectionCountMap.put(ipAddr, emailAndCount);
|
||||||
}
|
// throw new MessageDeliveryException(ExceptionEnum.fromCode(ExceptionEnum.ACCOUNT_HAS_CONNECTED));
|
||||||
|
//}
|
||||||
|
}else{
|
||||||
|
EmailLimit emailLimit = new EmailLimit();
|
||||||
|
emailLimit.setEmail(email);
|
||||||
|
emailLimit.setCount(1);
|
||||||
|
ipConnectionCountMap.put(key,emailLimit );
|
||||||
}
|
}
|
||||||
ipConnectionCountMap.put(ipAddr,email);
|
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
throw new MessageDeliveryException(ExceptionEnum.fromCode(ExceptionEnum.GET_PRINCIPAL_FAIL));
|
throw new MessageDeliveryException(ExceptionEnum.fromCode(ExceptionEnum.GET_PRINCIPAL_FAIL));
|
||||||
}
|
}
|
||||||
@@ -151,14 +177,24 @@ public class WebsocketChannelInterceptor implements ChannelInterceptor {
|
|||||||
/**
|
/**
|
||||||
* 断开链接处理
|
* 断开链接处理
|
||||||
*/
|
*/
|
||||||
private void disconnectHandler(StompHeaderAccessor accessor){
|
private void disconnectHandler(StompHeaderAccessor accessor,String email){
|
||||||
//连接数减一
|
//连接数减一
|
||||||
connectionCount.decrementAndGet();
|
connectionCount.decrementAndGet();
|
||||||
//断开链接的ip
|
//断开链接的ip
|
||||||
Map<String, Object> sessionAttributes = accessor.getSessionAttributes();
|
Map<String, Object> sessionAttributes = accessor.getSessionAttributes();
|
||||||
if (sessionAttributes != null) {
|
if (sessionAttributes != null ) {
|
||||||
String ipAddr = (String) sessionAttributes.get(IPADDR);
|
String ipAddr = (String) sessionAttributes.get(IPADDR);
|
||||||
ipConnectionCountMap.remove(ipAddr);
|
String key = ipAddr + email;
|
||||||
|
EmailLimit emailAndCount = ipConnectionCountMap.get(key);
|
||||||
|
if (emailAndCount != null ){
|
||||||
|
if (emailAndCount.getCount() > 1){
|
||||||
|
emailAndCount.setCount(emailAndCount.getCount() - 1);
|
||||||
|
}else{
|
||||||
|
ipConnectionCountMap.remove(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
throw new MessageDeliveryException(ExceptionEnum.fromCode(ExceptionEnum.GET_PRINCIPAL_FAIL));
|
throw new MessageDeliveryException(ExceptionEnum.fromCode(ExceptionEnum.GET_PRINCIPAL_FAIL));
|
||||||
}
|
}
|
||||||
@@ -186,4 +222,13 @@ public class WebsocketChannelInterceptor implements ChannelInterceptor {
|
|||||||
@Override
|
@Override
|
||||||
public void afterReceiveCompletion(@Nullable Message<?> message, MessageChannel channel, @Nullable Exception ex) {
|
public void afterReceiveCompletion(@Nullable Message<?> message, MessageChannel channel, @Nullable Exception ex) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ip限制存储对象
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
private class EmailLimit{
|
||||||
|
private String email;
|
||||||
|
private int count = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
package com.m2pool.chat.listener;
|
package com.m2pool.chat.listener;
|
||||||
|
|
||||||
|
import com.m2pool.chat.constant.ExceptionEnum;
|
||||||
import com.m2pool.chat.entity.StompPrincipal;
|
import com.m2pool.chat.entity.StompPrincipal;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.ApplicationListener;
|
import org.springframework.context.ApplicationListener;
|
||||||
|
import org.springframework.messaging.MessageDeliveryException;
|
||||||
import org.springframework.messaging.simp.SimpMessagingTemplate;
|
import org.springframework.messaging.simp.SimpMessagingTemplate;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@@ -18,5 +20,9 @@ public class IpLimitListener implements ApplicationListener<IpLimitEvent> {
|
|||||||
// messagingTemplate.convertAndSendToUser(principal.getName(),
|
// messagingTemplate.convertAndSendToUser(principal.getName(),
|
||||||
// Destination.QUEUE + "/" + principal.getName()
|
// Destination.QUEUE + "/" + principal.getName()
|
||||||
// , "ip链接数限制");
|
// , "ip链接数限制");
|
||||||
|
|
||||||
|
throw new MessageDeliveryException(ExceptionEnum.fromCode(ExceptionEnum.IP_LIMIT_CONNECT));
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,12 +42,20 @@ public class WebSocketEventListener implements ApplicationListener<SessionDiscon
|
|||||||
StompPrincipal user = (StompPrincipal) event.getUser();
|
StompPrincipal user = (StompPrincipal) event.getUser();
|
||||||
Message<byte[]> message = event.getMessage();
|
Message<byte[]> message = event.getMessage();
|
||||||
StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
|
StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
|
||||||
if (user != null && accessor.getCommand() == StompCommand.DISCONNECT && TOURIST.equals(user.getType())) {
|
if (user != null) {
|
||||||
//游客断开链接,通知客服删除游客聊天室
|
LOGGER.info("用户{}断开链接:用户类型{},消息类型{}",user.getName(), user.getType(), accessor.getCommand());
|
||||||
stompService.customerCloseRoom(user.getName());
|
if (accessor.getCommand() == StompCommand.DISCONNECT && TOURIST.equals(user.getType())) {
|
||||||
// 删除数据库中游客数据
|
//游客断开链接,通知客服删除游客聊天室
|
||||||
chatRoomMapper.delete(new LambdaUpdateWrapper<ChatRoom>().eq(ChatRoom::getUserOneEmail, user.getName()));
|
stompService.customerCloseRoom(user.getName());
|
||||||
chatMessageMapper.delete(new LambdaUpdateWrapper<ChatMessage>().eq(ChatMessage::getSendEmail, user.getName()));
|
// 删除数据库中游客数据
|
||||||
|
int delete = chatRoomMapper.delete(new LambdaUpdateWrapper<ChatRoom>()
|
||||||
|
.eq(ChatRoom::getUserOneEmail, user.getName()).like(ChatRoom::getUserOneEmail, "guest_"));
|
||||||
|
int delete1 = chatMessageMapper.delete(new LambdaUpdateWrapper<ChatMessage>()
|
||||||
|
.eq(ChatMessage::getSendEmail, user.getName()).like(ChatMessage::getSendEmail, "guest_"));
|
||||||
|
LOGGER.info("删除游客聊天室个数:{},消息个数{}", delete,delete1);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,4 +31,11 @@ public interface ChatMessageMapper extends BaseMapper<ChatMessage> {
|
|||||||
@MapKey("userEmail")
|
@MapKey("userEmail")
|
||||||
Map<String, Map<String,Integer>> findUnReadNums(@Param("userEmails") List<String> userEmails);
|
Map<String, Map<String,Integer>> findUnReadNums(@Param("userEmails") List<String> userEmails);
|
||||||
|
|
||||||
}
|
|
||||||
|
/**
|
||||||
|
* 查询当前客服参与过的所有聊天室
|
||||||
|
* @param userEmail
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
List<Long> findRoomIdsByCustomerEmail(@Param("userEmail") String userEmail);
|
||||||
|
}
|
||||||
|
|||||||
@@ -16,10 +16,10 @@ public interface ChatRoomMapper extends BaseMapper<ChatRoom> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询客服的聊天室列表
|
* 查询客服的聊天室列表
|
||||||
* @param userEmail 客服邮箱
|
* @param ids 要查询的聊天室集合
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
List<ChatRoomDto> findRoomList(@Param("userEmail") String userEmail, @Param("sendDateTime") LocalDateTime sendDateTime);
|
List<ChatRoomDto> findRoomList(@Param("ids") List<Long> ids, @Param("sendDateTime") LocalDateTime sendDateTime);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -30,6 +30,10 @@ public interface ChatRoomMapper extends BaseMapper<ChatRoom> {
|
|||||||
*/
|
*/
|
||||||
ChatRoomDto findRoomByUserEmail(@Param("userEmail") String userEmail);
|
ChatRoomDto findRoomByUserEmail(@Param("userEmail") String userEmail);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增或修改聊天室
|
||||||
|
* @param room
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
int insetOrUpdateRoom(@Param("room") ChatRoom room);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,4 +13,11 @@ public interface StompService {
|
|||||||
*/
|
*/
|
||||||
AjaxResult sendMessageToUser(StompPrincipal principal, UserMessageVo userMessageVo);
|
AjaxResult sendMessageToUser(StompPrincipal principal, UserMessageVo userMessageVo);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送消息给客服
|
||||||
|
* @param userMessageVo
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
AjaxResult sendMessageToCustomer(StompPrincipal principal, UserMessageVo userMessageVo);
|
||||||
}
|
}
|
||||||
@@ -9,6 +9,7 @@ import com.m2pool.chat.mapper.ChatMessageMapper;
|
|||||||
import com.m2pool.chat.mapper.ChatRoomMapper;
|
import com.m2pool.chat.mapper.ChatRoomMapper;
|
||||||
import com.m2pool.chat.service.ChatMessageService;
|
import com.m2pool.chat.service.ChatMessageService;
|
||||||
import com.m2pool.common.core.Result.R;
|
import com.m2pool.common.core.Result.R;
|
||||||
|
import com.m2pool.common.core.utils.StringUtils;
|
||||||
import com.m2pool.common.security.utils.SecurityUtils;
|
import com.m2pool.common.security.utils.SecurityUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
@@ -17,8 +18,7 @@ import javax.annotation.Resource;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import static com.m2pool.chat.constant.UserType.CUSTOMER;
|
import static com.m2pool.chat.constant.UserType.*;
|
||||||
import static com.m2pool.chat.constant.UserType.LOGIN_USER;
|
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class ChatMessageServiceImpl implements ChatMessageService {
|
public class ChatMessageServiceImpl implements ChatMessageService {
|
||||||
@@ -44,11 +44,18 @@ public class ChatMessageServiceImpl implements ChatMessageService {
|
|||||||
@Override
|
@Override
|
||||||
public R<List<ChatMessageDto>> findRecentlyMessage(String email,Long id,Integer pageNum,Long roomId) {
|
public R<List<ChatMessageDto>> findRecentlyMessage(String email,Long id,Integer pageNum,Long roomId) {
|
||||||
ChatMessage chatMessage;
|
ChatMessage chatMessage;
|
||||||
|
if(StringUtils.isEmpty(email)){
|
||||||
|
return R.fail("查询失败,用户标识或邮箱不能为空");
|
||||||
|
}
|
||||||
|
if(roomId == null){
|
||||||
|
return R.fail("查询聊天消息失败,聊天室ID不能为空");
|
||||||
|
}
|
||||||
|
//判断当前消息是否是七天内消息
|
||||||
if(id != null && id != 0){
|
if(id != null && id != 0){
|
||||||
chatMessage = chatMessageMapper.selectById(id);
|
chatMessage = chatMessageMapper.selectById(id);
|
||||||
}else{
|
}else{
|
||||||
chatMessage = chatMessageMapper.selectOne(new LambdaQueryWrapper<ChatMessage>()
|
chatMessage = chatMessageMapper.selectOne(new LambdaQueryWrapper<ChatMessage>()
|
||||||
.eq(ChatMessage::getRoomId, roomId).last("LIMIT 1"));
|
.eq(ChatMessage::getRoomId, roomId).orderByDesc(ChatMessage::getId).last("LIMIT 1"));
|
||||||
}
|
}
|
||||||
List<ChatMessageDto> recentlyMessage;
|
List<ChatMessageDto> recentlyMessage;
|
||||||
if(chatMessage != null){
|
if(chatMessage != null){
|
||||||
@@ -81,7 +88,7 @@ public class ChatMessageServiceImpl implements ChatMessageService {
|
|||||||
.id(roomId)
|
.id(roomId)
|
||||||
.build();
|
.build();
|
||||||
if (chatRoom != null){
|
if (chatRoom != null){
|
||||||
if (Objects.equals(type, LOGIN_USER)) {
|
if (Objects.equals(type, LOGIN_USER) || Objects.equals(type, TOURIST) ) {
|
||||||
build.setClientReadNum(0);
|
build.setClientReadNum(0);
|
||||||
}
|
}
|
||||||
if(Objects.equals(type, CUSTOMER)){
|
if(Objects.equals(type, CUSTOMER)){
|
||||||
@@ -92,4 +99,4 @@ public class ChatMessageServiceImpl implements ChatMessageService {
|
|||||||
}
|
}
|
||||||
return R.fail("聊天室不存在");
|
return R.fail("聊天室不存在");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
package com.m2pool.chat.service.impl;
|
package com.m2pool.chat.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import com.github.pagehelper.PageHelper;
|
import com.github.pagehelper.PageHelper;
|
||||||
import com.github.pagehelper.PageInfo;
|
import com.github.pagehelper.PageInfo;
|
||||||
|
import com.m2pool.chat.config.CustomWebSocketConfig;
|
||||||
import com.m2pool.chat.dto.ChatRoomDto;
|
import com.m2pool.chat.dto.ChatRoomDto;
|
||||||
import com.m2pool.chat.entity.ChatRoom;
|
import com.m2pool.chat.entity.ChatRoom;
|
||||||
import com.m2pool.chat.mapper.ChatMessageMapper;
|
import com.m2pool.chat.mapper.ChatMessageMapper;
|
||||||
@@ -11,6 +13,7 @@ import com.m2pool.chat.service.ChatRoomService;
|
|||||||
import com.m2pool.chat.vo.CharRoomVo;
|
import com.m2pool.chat.vo.CharRoomVo;
|
||||||
import com.m2pool.chat.vo.RoomPageVo;
|
import com.m2pool.chat.vo.RoomPageVo;
|
||||||
import com.m2pool.chat.vo.RoomVo;
|
import com.m2pool.chat.vo.RoomVo;
|
||||||
|
import com.m2pool.chat.vo.UserMessageVo;
|
||||||
import com.m2pool.common.core.Result.R;
|
import com.m2pool.common.core.Result.R;
|
||||||
import com.m2pool.common.core.constant.HttpStatus;
|
import com.m2pool.common.core.constant.HttpStatus;
|
||||||
import com.m2pool.common.core.utils.PageUtils;
|
import com.m2pool.common.core.utils.PageUtils;
|
||||||
@@ -20,13 +23,17 @@ import com.m2pool.system.api.RemoteUserService;
|
|||||||
import com.m2pool.system.api.entity.SysUser;
|
import com.m2pool.system.api.entity.SysUser;
|
||||||
import io.jsonwebtoken.lang.Collections;
|
import io.jsonwebtoken.lang.Collections;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.messaging.simp.user.SimpUser;
|
||||||
import org.springframework.messaging.simp.user.SimpUserRegistry;
|
import org.springframework.messaging.simp.user.SimpUserRegistry;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class ChatRoomServiceImpl extends ServiceImpl<ChatRoomMapper, ChatRoom> implements ChatRoomService {
|
public class ChatRoomServiceImpl extends ServiceImpl<ChatRoomMapper, ChatRoom> implements ChatRoomService {
|
||||||
@@ -43,15 +50,21 @@ public class ChatRoomServiceImpl extends ServiceImpl<ChatRoomMapper, ChatRoom> i
|
|||||||
@Autowired
|
@Autowired
|
||||||
private SimpUserRegistry userRegistry;
|
private SimpUserRegistry userRegistry;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private CustomWebSocketConfig webSocketConfig;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TableDataInfo<ChatRoomDto> findRoomList(RoomPageVo roomPageVo) {
|
public TableDataInfo<ChatRoomDto> findRoomList(RoomPageVo roomPageVo) {
|
||||||
String userEmail = SecurityUtils.getUsername();
|
String userEmail = SecurityUtils.getUsername();
|
||||||
PageHelper.startPage(1, 20);
|
List<Long> ids = chatMessageMapper.findRoomIdsByCustomerEmail(userEmail);
|
||||||
|
List<ChatRoomDto> roomList = new ArrayList<>();
|
||||||
|
if (ids.isEmpty()){
|
||||||
|
return getDataTable(roomList);
|
||||||
|
}
|
||||||
//1.查找当前客服对应的聊天室
|
//1.查找当前客服对应的聊天室
|
||||||
List<ChatRoomDto> roomList = chatRoomMapper.findRoomList(userEmail,roomPageVo.getSendDateTime());
|
roomList = chatRoomMapper.findRoomList(ids,roomPageVo.getSendDateTime());
|
||||||
|
|
||||||
|
|
||||||
PageUtils.clearPage();
|
|
||||||
// if (roomList.isEmpty()){
|
// if (roomList.isEmpty()){
|
||||||
// TableDataInfo tableDataInfo = new TableDataInfo();
|
// TableDataInfo tableDataInfo = new TableDataInfo();
|
||||||
// tableDataInfo.setCode(HttpStatus.ERROR);
|
// tableDataInfo.setCode(HttpStatus.ERROR);
|
||||||
@@ -72,33 +85,98 @@ public class ChatRoomServiceImpl extends ServiceImpl<ChatRoomMapper, ChatRoom> i
|
|||||||
rspData.setTotalPage(pageInfo.getPages());
|
rspData.setTotalPage(pageInfo.getPages());
|
||||||
return rspData;
|
return rspData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public R<ChatRoomDto> findRoomByUserid(RoomVo roomVo) {
|
public R<ChatRoomDto> findRoomByUserid(RoomVo roomVo) {
|
||||||
|
Random random = new Random();
|
||||||
//1.查询当前用户与对应用户是否已存在创建的聊天室
|
//1.查询当前用户与对应用户是否已存在创建的聊天室
|
||||||
String userEmail = roomVo.getEmail();
|
String userEmail = roomVo.getEmail();
|
||||||
ChatRoomDto roomByUserEmail = chatRoomMapper.findRoomByUserEmail(userEmail);
|
ChatRoomDto roomByUserEmail = chatRoomMapper.findRoomByUserEmail(userEmail);
|
||||||
|
System.out.println("bby-用户邮箱"+roomByUserEmail);
|
||||||
|
//获取nacos中配置的客服邮箱列表,这个列表中的邮箱实际可能不是客服角色,但能够行驶客服角色功能
|
||||||
|
List<String> customerEmails = new ArrayList<>(Arrays.asList(webSocketConfig.getDefaultCustomerEmail().split(",")));
|
||||||
|
int i = random.nextInt(customerEmails.size());
|
||||||
|
String email = customerEmails.get(i);
|
||||||
|
customerEmails.removeIf(email1 -> !checkOnline(email1));
|
||||||
if(roomByUserEmail != null){
|
if(roomByUserEmail != null){
|
||||||
|
System.out.println("bby-在线的客服"+customerEmails + "初始化分配的客服"+email+"聊天室信息"+roomByUserEmail);
|
||||||
|
//1.1 客服在线,并且在客服列表
|
||||||
|
if (checkOnline(roomByUserEmail.getUserEmail()) && customerEmails.contains(roomByUserEmail.getUserEmail())) {
|
||||||
|
roomByUserEmail.setCustomerIsOnline(true);
|
||||||
|
}
|
||||||
|
// 1.2客服账号不在担任客服角色,选择使用nacos默认配置中的客服角色,并修改数据库中的聊天室信息为新的客服角色。
|
||||||
|
if(!customerEmails.contains(roomByUserEmail.getUserEmail())){
|
||||||
|
roomByUserEmail.setCustomerIsOnline(false);
|
||||||
|
if (!customerEmails.isEmpty()){
|
||||||
|
email = customerEmails.get(random.nextInt(customerEmails.size()));
|
||||||
|
roomByUserEmail.setUserEmail(email);
|
||||||
|
roomByUserEmail.setCustomerIsOnline(true);
|
||||||
|
}
|
||||||
|
chatRoomMapper.updateById(ChatRoom.builder().id(roomByUserEmail.getId()).userTwoEmail(email).build());
|
||||||
|
}
|
||||||
|
// 1.3客服不在线,不在线情况如果从nacos配置中获取到多个客服,选择一个在线的客服发送。
|
||||||
|
if (!checkOnline(roomByUserEmail.getUserEmail())){
|
||||||
|
roomByUserEmail.setCustomerIsOnline(false);
|
||||||
|
if (!customerEmails.isEmpty()){
|
||||||
|
roomByUserEmail.setCustomerIsOnline(true);
|
||||||
|
email = customerEmails.get(random.nextInt(customerEmails.size()));
|
||||||
|
roomByUserEmail.setUserEmail(email);
|
||||||
|
}
|
||||||
|
}
|
||||||
return R.success(roomByUserEmail);
|
return R.success(roomByUserEmail);
|
||||||
}
|
}
|
||||||
|
|
||||||
//2.不存在创建一个聊天室
|
//2.不存在创建一个聊天室
|
||||||
List<SysUser> data = remoteUserService.getCSList().getData();
|
List<SysUser> data = remoteUserService.getCSList().getData();
|
||||||
if(Collections.isEmpty(data)){
|
List<String> emails = data.stream().map(SysUser::getEmail).collect(Collectors.toList());
|
||||||
return R.fail("客服人数不足");
|
emails.removeIf(email1 -> !checkOnline(email1));
|
||||||
|
|
||||||
|
//如果当前没有客服角色账号,使用nacos 默认配置中的客服角色
|
||||||
|
if(Collections.isEmpty(emails)){
|
||||||
|
emails = customerEmails;
|
||||||
|
// 自己不能创建
|
||||||
|
if(emails.contains( userEmail)){
|
||||||
|
return R.fail("您作为管理员无法创建与自己的连接");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Random random = new Random();
|
System.out.println("bby-在线的客服-创建聊天室emails"+emails);
|
||||||
SysUser sysUser = data.get(random.nextInt(data.size()));
|
boolean customerIsOnline = false;
|
||||||
ChatRoom build = ChatRoom.builder().userOneEmail(userEmail).userTwoEmail(sysUser.getEmail()).build();
|
//有在线客服,再次分配给在线的客服
|
||||||
int insert = chatRoomMapper.insert(build);
|
if (!emails.isEmpty()){
|
||||||
if (insert > 0){
|
customerIsOnline = true;
|
||||||
return R.success(ChatRoomDto.builder().id(String.valueOf(build.getId())).selfEmail(userEmail).userEmail(build.getUserTwoEmail()).build());
|
email = emails.get(random.nextInt(emails.size()));
|
||||||
|
System.out.println("bby-最终分配的在线客服"+email);
|
||||||
}
|
}
|
||||||
|
ChatRoom build = ChatRoom.builder()
|
||||||
|
.userOneEmail(userEmail)
|
||||||
|
.userTwoEmail(email)
|
||||||
|
.build();
|
||||||
|
try{
|
||||||
|
int insert = chatRoomMapper.insetOrUpdateRoom(build);
|
||||||
|
if (insert > 0){
|
||||||
|
return R.success(ChatRoomDto.builder()
|
||||||
|
.id(build.getId())
|
||||||
|
.selfEmail(userEmail)
|
||||||
|
.customerIsOnline(customerIsOnline)
|
||||||
|
.userEmail(build.getUserTwoEmail()).build());
|
||||||
|
}
|
||||||
|
}catch (Exception e){
|
||||||
|
return R.fail("聊天室已存在,创建聊天室失败");
|
||||||
|
}
|
||||||
|
|
||||||
return R.fail("聊天室不存在,并且创建聊天室失败");
|
return R.fail("聊天室不存在,并且创建聊天室失败");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查用户是否在线
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private boolean checkOnline(String email){
|
||||||
|
return userRegistry.getUsers().stream()
|
||||||
|
.anyMatch(user -> user.getName().equals(email));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public R<String> updateRoom(CharRoomVo charRoomVo) {
|
public R<String> updateRoom(CharRoomVo charRoomVo) {
|
||||||
int i = chatRoomMapper.updateById(ChatRoom.builder().id(charRoomVo.getId()).flag(charRoomVo.getFlag()).build());
|
int i = chatRoomMapper.updateById(ChatRoom.builder().id(charRoomVo.getId()).flag(charRoomVo.getFlag()).build());
|
||||||
@@ -107,4 +185,4 @@ public class ChatRoomServiceImpl extends ServiceImpl<ChatRoomMapper, ChatRoom> i
|
|||||||
}
|
}
|
||||||
return R.fail("修改失败,不存在该聊天室");
|
return R.fail("修改失败,不存在该聊天室");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.m2pool.chat.service.impl;
|
|||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.m2pool.chat.config.CustomWebSocketConfig;
|
import com.m2pool.chat.config.CustomWebSocketConfig;
|
||||||
import com.m2pool.chat.constant.Destination;
|
import com.m2pool.chat.constant.Destination;
|
||||||
|
import com.m2pool.chat.constant.ExceptionEnum;
|
||||||
import com.m2pool.chat.dto.WebsocketMessageDto;
|
import com.m2pool.chat.dto.WebsocketMessageDto;
|
||||||
import com.m2pool.chat.entity.ChatMessage;
|
import com.m2pool.chat.entity.ChatMessage;
|
||||||
import com.m2pool.chat.entity.ChatRoom;
|
import com.m2pool.chat.entity.ChatRoom;
|
||||||
@@ -13,6 +14,7 @@ import com.m2pool.chat.service.StompService;
|
|||||||
import com.m2pool.chat.vo.UserMessageVo;
|
import com.m2pool.chat.vo.UserMessageVo;
|
||||||
import com.m2pool.common.core.web.Result.AjaxResult;
|
import com.m2pool.common.core.web.Result.AjaxResult;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.messaging.MessageDeliveryException;
|
||||||
import org.springframework.messaging.simp.SimpMessagingTemplate;
|
import org.springframework.messaging.simp.SimpMessagingTemplate;
|
||||||
import org.springframework.messaging.simp.user.SimpUserRegistry;
|
import org.springframework.messaging.simp.user.SimpUserRegistry;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@@ -23,7 +25,11 @@ import org.springframework.transaction.support.TransactionTemplate;
|
|||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import static com.alibaba.nacos.client.utils.EnvUtil.LOGGER;
|
||||||
import static com.m2pool.chat.constant.UserType.CUSTOMER;
|
import static com.m2pool.chat.constant.UserType.CUSTOMER;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@@ -47,8 +53,61 @@ public class StompServiceImpl implements StompService {
|
|||||||
@Resource
|
@Resource
|
||||||
private CustomWebSocketConfig webSocketConfig;
|
private CustomWebSocketConfig webSocketConfig;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* key 为发送者+接受者 ,value 为 图片内容
|
||||||
|
*/
|
||||||
|
//private final ConcurrentHashMap<String, String> imageContent = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AjaxResult sendMessageToUser(StompPrincipal principal, UserMessageVo userMessageVo) {
|
public AjaxResult sendMessageToUser(StompPrincipal principal, UserMessageVo userMessageVo) {
|
||||||
|
WebsocketMessageDto build = buildDto(principal, userMessageVo);
|
||||||
|
//获取当前聊天室对象
|
||||||
|
ChatRoom chatRoom = chatRoomMapper.selectOne(new LambdaQueryWrapper<ChatRoom>()
|
||||||
|
.eq(ChatRoom::getUserOneEmail,userMessageVo.getEmail())
|
||||||
|
.eq(ChatRoom::getUserTwoEmail,principal.getName()));
|
||||||
|
build(chatRoom,userMessageVo,principal,build);
|
||||||
|
messagingTemplate.convertAndSendToUser(principal.getName(), Destination.QUEUE_CUSTOMER + "/" + principal.getName(),build);
|
||||||
|
messagingTemplate.convertAndSendToUser(userMessageVo.getEmail(), Destination.QUEUE_USER + "/" + userMessageVo.getEmail(),build);
|
||||||
|
return AjaxResult.success("成功");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AjaxResult sendMessageToCustomer(StompPrincipal principal, UserMessageVo userMessageVo) {
|
||||||
|
WebsocketMessageDto build = buildDto(principal, userMessageVo);
|
||||||
|
ChatRoom chatRoom = chatRoomMapper.selectOne(new LambdaQueryWrapper<ChatRoom>()
|
||||||
|
.eq(ChatRoom::getUserOneEmail, principal.getName())
|
||||||
|
.eq(ChatRoom::getUserTwoEmail, userMessageVo.getEmail()));
|
||||||
|
build(chatRoom,userMessageVo,principal,build);
|
||||||
|
messagingTemplate.convertAndSendToUser(principal.getName(), Destination.QUEUE_USER + "/" + principal.getName(),build);
|
||||||
|
messagingTemplate.convertAndSendToUser(userMessageVo.getEmail(), Destination.QUEUE_CUSTOMER + "/" + userMessageVo.getEmail(),build);
|
||||||
|
|
||||||
|
return AjaxResult.success("成功");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void build(ChatRoom chatRoom,UserMessageVo userMessageVo,StompPrincipal principal,WebsocketMessageDto build){
|
||||||
|
if (chatRoom == null && userMessageVo.getRoomId() == null){
|
||||||
|
throw new MessageDeliveryException(ExceptionEnum.fromCode(ExceptionEnum.ROOM_NOT_EXIST));
|
||||||
|
}
|
||||||
|
if(chatRoom != null && userMessageVo.getRoomId() == null){
|
||||||
|
userMessageVo.setRoomId(chatRoom.getId());
|
||||||
|
}
|
||||||
|
build.setRoomId(userMessageVo.getRoomId());
|
||||||
|
int serviceReadNum = chatRoom != null ? chatRoom.getServiceReadNum() : 0;
|
||||||
|
build.setClientReadNum(serviceReadNum + 1);
|
||||||
|
Long id = executeTran(principal, userMessageVo, chatRoom);
|
||||||
|
System.out.println("发送消息,聊天室id"+userMessageVo.getRoomId()+"发送者邮箱"+principal.getName()+"接受者邮箱"+userMessageVo.getEmail()+"消息id"+id);
|
||||||
|
// 多端情况下,需要把消息发送给
|
||||||
|
build.setId(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建聊天实时返回信息
|
||||||
|
* @param principal
|
||||||
|
* @param userMessageVo
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private WebsocketMessageDto buildDto(StompPrincipal principal, UserMessageVo userMessageVo) {
|
||||||
Boolean isCreate = principal.getIsCreate();
|
Boolean isCreate = principal.getIsCreate();
|
||||||
WebsocketMessageDto build = WebsocketMessageDto.builder()
|
WebsocketMessageDto build = WebsocketMessageDto.builder()
|
||||||
.type(userMessageVo.getType())
|
.type(userMessageVo.getType())
|
||||||
@@ -62,37 +121,26 @@ public class StompServiceImpl implements StompService {
|
|||||||
if (isCreate){
|
if (isCreate){
|
||||||
principal.setIsCreate(false);
|
principal.setIsCreate(false);
|
||||||
}
|
}
|
||||||
//获取当前聊天室对象
|
return build;
|
||||||
ChatRoom chatRoom;
|
}
|
||||||
|
|
||||||
if(!CUSTOMER.equals(principal.getType())){
|
/**
|
||||||
chatRoom = chatRoomMapper.selectOne(new LambdaQueryWrapper<ChatRoom>()
|
* 执行消息表新增消息和聊天室已读未读消息数量更新事务
|
||||||
.eq(ChatRoom::getUserOneEmail, principal.getName())
|
* @param principal
|
||||||
.eq(ChatRoom::getUserTwoEmail, userMessageVo.getEmail()));
|
* @param userMessageVo
|
||||||
build.setRoomId(String.valueOf(userMessageVo.getRoomId()));
|
* @param chatRoom
|
||||||
build.setClientReadNum(chatRoom.getServiceReadNum() + 1);
|
*/
|
||||||
}else {
|
private Long executeTran(StompPrincipal principal, UserMessageVo userMessageVo, ChatRoom chatRoom){
|
||||||
chatRoom = chatRoomMapper.selectOne(new LambdaQueryWrapper<ChatRoom>()
|
final Long[] id = {0L};
|
||||||
.eq(ChatRoom::getUserOneEmail, userMessageVo.getEmail())
|
|
||||||
.eq(ChatRoom::getUserTwoEmail, principal.getName()));
|
|
||||||
build.setRoomId(String.valueOf(userMessageVo.getRoomId()));
|
|
||||||
build.setClientReadNum(chatRoom.getClientReadNum() + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean bool = checkOnline(userMessageVo);
|
|
||||||
//在线用户才发送消息
|
|
||||||
if (bool){
|
|
||||||
messagingTemplate.convertAndSendToUser(userMessageVo.getEmail(), Destination.QUEUE + "/" + userMessageVo.getEmail(),build);
|
|
||||||
}
|
|
||||||
// 消息存储
|
// 消息存储
|
||||||
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
|
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
|
||||||
@Override
|
@Override
|
||||||
protected void doInTransactionWithoutResult(TransactionStatus status) {
|
protected void doInTransactionWithoutResult(TransactionStatus status) {
|
||||||
try {
|
try {
|
||||||
// 插入消息并获取 ID
|
// 插入消息并获取 ID
|
||||||
insertMessage(principal,userMessageVo);
|
id[0] = insertMessage(principal, userMessageVo);
|
||||||
//聊天室,已读未读数量,更新。
|
//聊天室,已读未读数量,更新。
|
||||||
updateRoom(chatRoom,principal.getType(),bool);
|
updateRoom(chatRoom,principal.getType());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// 回滚事务
|
// 回滚事务
|
||||||
status.setRollbackOnly();
|
status.setRollbackOnly();
|
||||||
@@ -100,8 +148,7 @@ public class StompServiceImpl implements StompService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
return id[0];
|
||||||
return AjaxResult.success("成功");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -109,6 +156,7 @@ public class StompServiceImpl implements StompService {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private boolean checkOnline(UserMessageVo userMessageVo){
|
private boolean checkOnline(UserMessageVo userMessageVo){
|
||||||
|
|
||||||
return userRegistry.getUsers().stream()
|
return userRegistry.getUsers().stream()
|
||||||
.anyMatch(user -> user.getName().equals(userMessageVo.getEmail()));
|
.anyMatch(user -> user.getName().equals(userMessageVo.getEmail()));
|
||||||
}
|
}
|
||||||
@@ -123,7 +171,7 @@ public class StompServiceImpl implements StompService {
|
|||||||
.sendEmail(principal.getName())
|
.sendEmail(principal.getName())
|
||||||
.content(userMessageVo.getContent())
|
.content(userMessageVo.getContent())
|
||||||
.type(userMessageVo.getType())
|
.type(userMessageVo.getType())
|
||||||
.roomId(Long.parseLong(userMessageVo.getRoomId()))
|
.roomId(userMessageVo.getRoomId())
|
||||||
.build();
|
.build();
|
||||||
chatMessageMapper.insert(message);
|
chatMessageMapper.insert(message);
|
||||||
return message.getId();
|
return message.getId();
|
||||||
@@ -133,30 +181,38 @@ public class StompServiceImpl implements StompService {
|
|||||||
* 修改聊天信息
|
* 修改聊天信息
|
||||||
* @param chatRoom 本次聊天聊天室信息
|
* @param chatRoom 本次聊天聊天室信息
|
||||||
* @param sendUserType 发送者类型
|
* @param sendUserType 发送者类型
|
||||||
* @param bool 发送者是否在线,不在线,需要更新未读消息数量
|
* @param {bool 废弃 发送者是否在线,不在线,需要更新未读消息数量}
|
||||||
*/
|
*/
|
||||||
private void updateRoom(ChatRoom chatRoom,Integer sendUserType,Boolean bool){
|
private void updateRoom(ChatRoom chatRoom,Integer sendUserType){
|
||||||
|
System.out.println("聊天室信息"+chatRoom);
|
||||||
ChatRoom room = ChatRoom.builder().id(chatRoom.getId()).build();
|
if(chatRoom != null){
|
||||||
if (CUSTOMER.equals(sendUserType)) {
|
ChatRoom room = ChatRoom.builder().id(chatRoom.getId()).build();
|
||||||
room.setClientReadNum(chatRoom.getClientReadNum() + 1);
|
if (CUSTOMER.equals(sendUserType)) {
|
||||||
room.setLastCustomerSendTime(LocalDateTime.now());
|
room.setClientReadNum(chatRoom.getClientReadNum() + 1);
|
||||||
} else {
|
room.setLastCustomerSendTime(LocalDateTime.now());
|
||||||
room.setServiceReadNum(chatRoom.getServiceReadNum() + 1);
|
} else {
|
||||||
room.setLastUserSendTime(LocalDateTime.now());
|
room.setServiceReadNum(chatRoom.getServiceReadNum() + 1);
|
||||||
|
room.setLastUserSendTime(LocalDateTime.now());
|
||||||
|
}
|
||||||
|
chatRoomMapper.updateById(room);
|
||||||
}
|
}
|
||||||
chatRoomMapper.updateById(room);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用于客服关闭断线客服端聊天室接口
|
* 用于客服关闭断线客服端聊天室接口
|
||||||
* @param roomId 游客与客服聊天室id, 实际为游客邮箱
|
* @param userName 游客邮箱
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public void customerCloseRoom(String roomId){
|
public void customerCloseRoom(String userName){
|
||||||
messagingTemplate.convertAndSendToUser(
|
//目前配置只配置了一个客服,如果多个关闭消息,需同时发送多个客服
|
||||||
webSocketConfig.getDefaultCustomerEmail(),
|
System.out.println("当前配置的客服"+webSocketConfig.getDefaultCustomerEmail());
|
||||||
Destination.QUEUE + Destination.QUEUE_CLOSE_ROOM + webSocketConfig.getDefaultCustomerEmail(),roomId);
|
String[] split = webSocketConfig.getDefaultCustomerEmail().split(",");
|
||||||
|
for (String email : split) {
|
||||||
|
messagingTemplate.convertAndSendToUser(
|
||||||
|
email,
|
||||||
|
Destination.QUEUE_CLOSE_ROOM + email, userName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,19 @@
|
|||||||
package com.m2pool.chat.task;
|
package com.m2pool.chat.task;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.m2pool.chat.entity.ChatMessage;
|
import com.m2pool.chat.entity.ChatMessage;
|
||||||
import com.m2pool.chat.entity.ChatMessageHistory;
|
import com.m2pool.chat.entity.ChatMessageHistory;
|
||||||
|
import com.m2pool.chat.entity.ChatRoom;
|
||||||
import com.m2pool.chat.mapper.ChatMessageMapper;
|
import com.m2pool.chat.mapper.ChatMessageMapper;
|
||||||
|
import com.m2pool.chat.mapper.ChatRoomMapper;
|
||||||
import com.m2pool.chat.service.ChatMessageHistoryService;
|
import com.m2pool.chat.service.ChatMessageHistoryService;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.cloud.context.config.annotation.RefreshScope;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
@@ -21,7 +29,9 @@ import java.util.stream.Collectors;
|
|||||||
* @Author yyb
|
* @Author yyb
|
||||||
* @Date 2025/4/15 11:51
|
* @Date 2025/4/15 11:51
|
||||||
*/
|
*/
|
||||||
|
@Data
|
||||||
@Configuration
|
@Configuration
|
||||||
|
@ConfigurationProperties(prefix = "task")
|
||||||
@EnableScheduling
|
@EnableScheduling
|
||||||
public class ChatTask {
|
public class ChatTask {
|
||||||
|
|
||||||
@@ -30,10 +40,18 @@ public class ChatTask {
|
|||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private ChatMessageHistoryService chatMessageHistoryService;
|
private ChatMessageHistoryService chatMessageHistoryService;
|
||||||
|
@Autowired
|
||||||
|
private ChatRoomMapper chatRoomMapper;
|
||||||
|
|
||||||
|
private boolean enable;
|
||||||
|
|
||||||
// @Scheduled(cron = "0 0/1 * * * ?")
|
// @Scheduled(cron = "0 0/1 * * * ?")
|
||||||
@Scheduled(cron = "0 15 1 * * ?")
|
@Scheduled(cron = "0 15 1 * * ?")
|
||||||
public void chatMessageDataSeparatedForHotAndCold(){
|
public void chatMessageDataSeparatedForHotAndCold(){
|
||||||
|
if(!enable){
|
||||||
|
System.out.println("ChatTask 定时任务已关闭,请在nacos修改配置");
|
||||||
|
return;
|
||||||
|
}
|
||||||
int pageNum = 1;
|
int pageNum = 1;
|
||||||
int pageSize = 1000; // 每批处理数量
|
int pageSize = 1000; // 每批处理数量
|
||||||
List<ChatMessage> chatMessages;
|
List<ChatMessage> chatMessages;
|
||||||
@@ -68,4 +86,20 @@ public class ChatTask {
|
|||||||
pageNum++;
|
pageNum++;
|
||||||
} while (!chatMessages.isEmpty());
|
} while (!chatMessages.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理掉,因服务器异常,未发送到客服这边删除的游客聊天室和消息表数据
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Scheduled(cron = "0 16 1 * * ?")
|
||||||
|
//@Scheduled(cron = "0 0/1 * * * ?")
|
||||||
|
public void clearTouristDatas(){
|
||||||
|
if(!enable){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
chatMessageMapper.delete(new LambdaUpdateWrapper<ChatMessage>()
|
||||||
|
.like(ChatMessage::getSendEmail, "guest_"));
|
||||||
|
chatRoomMapper.delete(new LambdaUpdateWrapper<ChatRoom>().like(ChatRoom::getUserOneEmail, "guest_"));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,14 @@
|
|||||||
package com.m2pool.chat.vo;
|
package com.m2pool.chat.vo;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.annotations.ApiModel;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ClassName UserMessageVo
|
* @ClassName UserMessageVo
|
||||||
* @Description 用户发送消息对象
|
* @Description 用户发送消息对象
|
||||||
@@ -42,5 +47,25 @@ public class UserMessageVo {
|
|||||||
* 聊天室id
|
* 聊天室id
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty(value = "聊天室id", example = "1")
|
@ApiModelProperty(value = "聊天室id", example = "1")
|
||||||
private String roomId;
|
private Long roomId;
|
||||||
|
|
||||||
|
///**
|
||||||
|
// * 总的分片数
|
||||||
|
// */
|
||||||
|
//@ApiModelProperty(value = "总的分片数", example = "1",required = false)
|
||||||
|
//private Integer totalChunks;
|
||||||
|
///**
|
||||||
|
// * 当前分片数
|
||||||
|
// */
|
||||||
|
//@ApiModelProperty(value = "当前分片数", example = "1",required = false)
|
||||||
|
//private Integer currentChunk;
|
||||||
|
//
|
||||||
|
///**
|
||||||
|
// * 是否是第一个分片
|
||||||
|
// */
|
||||||
|
//@ApiModelProperty(value = "是否是第一个分片", example = "true",required = false)
|
||||||
|
//private Boolean isFirstChunk;
|
||||||
|
//
|
||||||
|
//@ApiModelProperty(value = "发送时间", example = "2025-05-27T15:39:29.221Z",required = false)
|
||||||
|
//private Date sendTime;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,4 +76,4 @@ websocket:
|
|||||||
send-time-limit: 5000 # 发送超时时间 5秒
|
send-time-limit: 5000 # 发送超时时间 5秒
|
||||||
send-buffer-size-limit: 65536 # 发送缓冲区大小 64K
|
send-buffer-size-limit: 65536 # 发送缓冲区大小 64K
|
||||||
time-to-first-message: 5000 # 首次消息超时时间 5秒
|
time-to-first-message: 5000 # 首次消息超时时间 5秒
|
||||||
max-connections: 100 # 最大连接数
|
max-connections: 100 # 最大连接数
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
spring:
|
spring:
|
||||||
profiles:
|
profiles:
|
||||||
active: test
|
active: prod
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
<where>
|
<where>
|
||||||
room_id = #{roomId}
|
room_id = #{roomId}
|
||||||
<if test="id != null">
|
<if test="id != null">
|
||||||
AND id <![CDATA[ <= ]]> #{id}
|
AND id <![CDATA[ < ]]> #{id}
|
||||||
</if>
|
</if>
|
||||||
</where>
|
</where>
|
||||||
ORDER BY id DESC
|
ORDER BY id DESC
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
<where>
|
<where>
|
||||||
room_id = #{roomId}
|
room_id = #{roomId}
|
||||||
<if test="id != null">
|
<if test="id != null">
|
||||||
AND id <![CDATA[ <= ]]> #{id}
|
AND id <![CDATA[ < ]]> #{id}
|
||||||
</if>
|
</if>
|
||||||
</where>
|
</where>
|
||||||
ORDER BY id DESC
|
ORDER BY id DESC
|
||||||
@@ -33,5 +33,12 @@
|
|||||||
AND is_read = false
|
AND is_read = false
|
||||||
GROUP BY send_email
|
GROUP BY send_email
|
||||||
</select>
|
</select>
|
||||||
|
<select id="findRoomIdsByCustomerEmail" resultType="java.lang.Long">
|
||||||
|
select room_id from chat_message where send_email = #{userEmail} group by room_id
|
||||||
|
UNION
|
||||||
|
select room_id from chat_message_history where send_email = #{userEmail} group by room_id
|
||||||
|
UNION
|
||||||
|
select id as room_id from chat_room where user_two_email = #{userEmail}
|
||||||
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|||||||
@@ -7,14 +7,21 @@
|
|||||||
id,
|
id,
|
||||||
user_one_email AS userEmail,
|
user_one_email AS userEmail,
|
||||||
flag,
|
flag,
|
||||||
last_user_send_time as lastUserSendTime,
|
CASE WHEN last_user_send_time >= last_customer_send_time
|
||||||
last_customer_send_time as lastCustomerSendTime,
|
THEN last_user_send_time ELSE last_customer_send_time END AS lastUserSendTime,
|
||||||
service_read_num AS clientReadNum
|
service_read_num AS clientReadNum
|
||||||
FROM
|
FROM
|
||||||
chat_room
|
chat_room
|
||||||
<where>
|
<where>
|
||||||
user_two_email = #{userEmail} AND del = false
|
del = false
|
||||||
<choose>
|
<choose>
|
||||||
|
<when test="ids != null and ids.size() > 0">
|
||||||
|
AND id IN
|
||||||
|
<foreach item="id" index="index" collection="ids"
|
||||||
|
open="(" separator="," close=")">
|
||||||
|
#{id}
|
||||||
|
</foreach>
|
||||||
|
</when>
|
||||||
<when test="sendDateTime != null">
|
<when test="sendDateTime != null">
|
||||||
AND last_user_send_time <![CDATA[ <= ]]> #{sendDateTime}
|
AND last_user_send_time <![CDATA[ <= ]]> #{sendDateTime}
|
||||||
</when>
|
</when>
|
||||||
@@ -22,11 +29,11 @@
|
|||||||
AND last_user_send_time <![CDATA[ <= ]]> NOW()
|
AND last_user_send_time <![CDATA[ <= ]]> NOW()
|
||||||
</otherwise>
|
</otherwise>
|
||||||
</choose>
|
</choose>
|
||||||
|
|
||||||
</where>
|
</where>
|
||||||
ORDER BY
|
ORDER BY
|
||||||
flag DESC,
|
flag DESC,
|
||||||
last_user_send_time DESC
|
GREATEST( last_user_send_time, last_customer_send_time ) DESC
|
||||||
|
LIMIT 20
|
||||||
</select>
|
</select>
|
||||||
<select id="findRoomByUserEmail" resultType="com.m2pool.chat.dto.ChatRoomDto">
|
<select id="findRoomByUserEmail" resultType="com.m2pool.chat.dto.ChatRoomDto">
|
||||||
SELECT
|
SELECT
|
||||||
@@ -36,4 +43,12 @@
|
|||||||
WHERE
|
WHERE
|
||||||
user_one_email = #{userEmail}
|
user_one_email = #{userEmail}
|
||||||
</select>
|
</select>
|
||||||
</mapper>
|
<insert id="insetOrUpdateRoom">
|
||||||
|
INSERT INTO chat_room(user_one_email,user_two_email)
|
||||||
|
VALUES (#{room.userOneEmail},#{room.userTwoEmail})
|
||||||
|
ON DUPLICATE KEY UPDATE
|
||||||
|
user_one_email = #{room.userOneEmail},
|
||||||
|
user_two_email = #{room.userTwoEmail}
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
</mapper>
|
||||||
|
|||||||
@@ -27,4 +27,4 @@ file:
|
|||||||
domain: https://www.m2pool.com
|
domain: https://www.m2pool.com
|
||||||
path: /var/www/html/web
|
path: /var/www/html/web
|
||||||
img: /img
|
img: /img
|
||||||
filepath: /home/ubuntu/prod
|
filepath: /home/ubuntu/prod
|
||||||
|
|||||||
@@ -27,4 +27,4 @@ file:
|
|||||||
path: /var/www/html/web_test
|
path: /var/www/html/web_test
|
||||||
# img: /img
|
# img: /img
|
||||||
filepath: /home/ubuntu/web
|
filepath: /home/ubuntu/web
|
||||||
prefix: /statics
|
prefix: /statics
|
||||||
|
|||||||
225
m2pool-modules/m2pool-lease/pom.xml
Normal file
225
m2pool-modules/m2pool-lease/pom.xml
Normal file
@@ -0,0 +1,225 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>m2pool-modules</artifactId>
|
||||||
|
<groupId>com.m2pool</groupId>
|
||||||
|
<version>3.5.0</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>m2pool-lease</artifactId>
|
||||||
|
<dependencies>
|
||||||
|
<!-- SpringCloud Alibaba Nacos -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!-- SpringCloud Alibaba Nacos Config -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- SpringCloud Alibaba Sentinel -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-amqp</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- SpringBoot Actuator -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Swagger UI -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.springfox</groupId>
|
||||||
|
<artifactId>springfox-swagger-ui</artifactId>
|
||||||
|
<version>${swagger.fox.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Mysql Connector -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>mysql</groupId>
|
||||||
|
<artifactId>mysql-connector-java</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Lombok -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok-maven-plugin</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- <!– Mybatis-Plus –>-->
|
||||||
|
<!-- <dependency>-->
|
||||||
|
<!-- <groupId>com.baomidou</groupId>-->
|
||||||
|
<!-- <artifactId>mybatis-plus-boot-starter</artifactId>-->
|
||||||
|
<!-- <exclusions>-->
|
||||||
|
<!-- <exclusion>-->
|
||||||
|
<!-- <artifactId>jsqlparser</artifactId>-->
|
||||||
|
<!-- <groupId>com.github.jsqlparser</groupId>-->
|
||||||
|
<!-- </exclusion>-->
|
||||||
|
<!--<!– <exclusion>–>-->
|
||||||
|
<!--<!– <artifactId>mybatis</artifactId>–>-->
|
||||||
|
<!--<!– <groupId>org.mybatis</groupId>–>-->
|
||||||
|
<!--<!– </exclusion>–>-->
|
||||||
|
<!-- </exclusions>-->
|
||||||
|
<!-- </dependency>-->
|
||||||
|
|
||||||
|
<!-- M2Pool Common DataSource -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.m2pool</groupId>
|
||||||
|
<artifactId>common-datasource</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- M2Pool Common security -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.m2pool</groupId>
|
||||||
|
<artifactId>common-security</artifactId>
|
||||||
|
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.m2pool</groupId>
|
||||||
|
<artifactId>common-log</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.m2pool</groupId>
|
||||||
|
<artifactId>common-swagger</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- WebSocket-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.java-websocket</groupId>
|
||||||
|
<artifactId>Java-WebSocket</artifactId>
|
||||||
|
<version>1.3.5</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
<artifactId>hutool-all</artifactId>
|
||||||
|
<version>5.6.2</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mybatis</groupId>
|
||||||
|
<artifactId>mybatis</artifactId>
|
||||||
|
<version>3.5.7</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.baomidou</groupId>
|
||||||
|
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||||
|
<version>3.5.3</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!--google两步认证相关-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>de.taimos</groupId>
|
||||||
|
<artifactId>totp</artifactId>
|
||||||
|
<version>1.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-codec</groupId>
|
||||||
|
<artifactId>commons-codec</artifactId>
|
||||||
|
<version>1.10</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.zxing</groupId>
|
||||||
|
<artifactId>javase</artifactId>
|
||||||
|
<version>3.3.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.java.dev.jna</groupId>
|
||||||
|
<artifactId>jna</artifactId>
|
||||||
|
<version>5.12.1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>pt.kcry</groupId>
|
||||||
|
<artifactId>blake3_3</artifactId>
|
||||||
|
<version>3.1.2</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<!-- 本地环境 -->
|
||||||
|
<id>dev</id>
|
||||||
|
<properties>
|
||||||
|
<spring.profile>dev</spring.profile>
|
||||||
|
<nacos.server.address>127.0.0.1:8808</nacos.server.address>
|
||||||
|
</properties>
|
||||||
|
<activation>
|
||||||
|
<!-- 是否默认激活 -->
|
||||||
|
<activeByDefault>true</activeByDefault>
|
||||||
|
</activation>
|
||||||
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<!-- 测试环境 -->
|
||||||
|
<id>test</id>
|
||||||
|
<properties>
|
||||||
|
<spring.profile>test</spring.profile>
|
||||||
|
<nacos.server.address>127.0.0.1:8808</nacos.server.address>
|
||||||
|
</properties>
|
||||||
|
<activation>
|
||||||
|
<activeByDefault>false</activeByDefault>
|
||||||
|
</activation>
|
||||||
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<!-- 生产环境 -->
|
||||||
|
<id>prod</id>
|
||||||
|
<properties>
|
||||||
|
<spring.profile>prod</spring.profile>
|
||||||
|
<nacos.server.address>127.0.0.1:8808</nacos.server.address>
|
||||||
|
</properties>
|
||||||
|
<activation>
|
||||||
|
<activeByDefault>false</activeByDefault>
|
||||||
|
</activation>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<finalName>${project.artifactId}</finalName>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
<version>2.5.6</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>repackage</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.m2pool.lease;
|
||||||
|
|
||||||
|
import com.m2pool.common.security.annotation.EnableCustomConfig;
|
||||||
|
import com.m2pool.common.security.annotation.EnableM2PoolFeignClients;
|
||||||
|
import com.m2pool.common.swagger.annotation.EnableCustomSwagger2;
|
||||||
|
import org.mybatis.spring.annotation.MapperScan;
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@EnableCustomConfig
|
||||||
|
@EnableCustomSwagger2
|
||||||
|
@EnableM2PoolFeignClients
|
||||||
|
@SpringBootApplication
|
||||||
|
@MapperScan({"com.m2pool.lease.mapper"})
|
||||||
|
public class M2poolLeaseApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(M2poolLeaseApplication.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
//package com.m2pool.lease.config;
|
||||||
|
//
|
||||||
|
//import com.m2pool.common.core.constant.SecurityConstants;
|
||||||
|
//import com.m2pool.common.core.context.SecurityContextHolder;
|
||||||
|
//import com.m2pool.common.core.utils.JwtUtils;
|
||||||
|
//import com.m2pool.common.core.utils.ServletUtils;
|
||||||
|
//import com.m2pool.common.security.utils.SecurityUtils;
|
||||||
|
//import org.springframework.stereotype.Component;
|
||||||
|
//import org.springframework.web.servlet.HandlerInterceptor;
|
||||||
|
//
|
||||||
|
//import javax.servlet.http.HttpServletRequest;
|
||||||
|
//import javax.servlet.http.HttpServletResponse;
|
||||||
|
//
|
||||||
|
////生产环境
|
||||||
|
//@Component
|
||||||
|
//public class AuthInterceptor implements HandlerInterceptor {
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||||
|
// // 获取请求头中的 Authorization 字段
|
||||||
|
//
|
||||||
|
// //System.out.println("获取到的Authorization:"+authorization + "666"+ SecurityUtils.getToken());
|
||||||
|
// //if (authorization != null) {
|
||||||
|
// // // 将 Authorization 值存入 ThreadLocal
|
||||||
|
// //
|
||||||
|
// //}
|
||||||
|
// String authorization = request.getHeader("Authorization");
|
||||||
|
//
|
||||||
|
// String userName = JwtUtils.getUserName(authorization);
|
||||||
|
// SecurityContextHolder.setUserName("liuyiqing0119@gmail.com");
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
|
||||||
|
// // 请求完成后清除 ThreadLocal 中的值,避免内存泄漏
|
||||||
|
// SecurityContextHolder.remove();
|
||||||
|
// }
|
||||||
|
//}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.m2pool.lease.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
@Configuration
|
||||||
|
public class CorsConfig implements WebMvcConfigurer {
|
||||||
|
@Override
|
||||||
|
public void addCorsMappings(CorsRegistry registry) {
|
||||||
|
registry.addMapping("/api/**")
|
||||||
|
.allowedOrigins("*") // 允许跨域
|
||||||
|
.allowedMethods("GET", "POST")
|
||||||
|
.allowedHeaders("Content-Type")
|
||||||
|
.allowCredentials(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.m2pool.lease.config;
|
||||||
|
|
||||||
|
import org.springframework.amqp.core.Message;
|
||||||
|
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
|
||||||
|
|
||||||
|
public class JacksonMessageConverter extends Jackson2JsonMessageConverter {
|
||||||
|
public JacksonMessageConverter() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object fromMessage(Message message) {
|
||||||
|
message.getMessageProperties().setContentType("application/json");
|
||||||
|
return super.fromMessage(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package com.m2pool.lease.config;//package com.m2pool.lease.config;
|
||||||
|
//
|
||||||
|
//import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
|
||||||
|
//import org.springframework.context.annotation.Bean;
|
||||||
|
//import org.springframework.context.annotation.Configuration;
|
||||||
|
//import springfox.documentation.builders.ApiInfoBuilder;
|
||||||
|
//import springfox.documentation.builders.PathSelectors;
|
||||||
|
//import springfox.documentation.builders.RequestHandlerSelectors;
|
||||||
|
//import springfox.documentation.service.ApiInfo;
|
||||||
|
//import springfox.documentation.spi.DocumentationType;
|
||||||
|
//import springfox.documentation.spring.web.plugins.Docket;
|
||||||
|
//import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
||||||
|
//
|
||||||
|
//@Configuration
|
||||||
|
//@EnableSwagger2
|
||||||
|
//@EnableKnife4j
|
||||||
|
//public class Knife4jConfiguration {
|
||||||
|
//
|
||||||
|
// @Bean
|
||||||
|
// public Docket createRestApi() {
|
||||||
|
// return new Docket(DocumentationType.SWAGGER_2)
|
||||||
|
// .useDefaultResponseMessages(false)
|
||||||
|
// .apiInfo(apiInfo())
|
||||||
|
// .select()
|
||||||
|
// .apis(RequestHandlerSelectors.basePackage("com.m2pool.lease.controller"))
|
||||||
|
// .paths(PathSelectors.any())
|
||||||
|
// .build();
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private ApiInfo apiInfo() {
|
||||||
|
// return new ApiInfoBuilder()
|
||||||
|
// .description("Kinfe4j 集成测试文档")
|
||||||
|
// .version("v1.0.0")
|
||||||
|
// .title("API测试文档")
|
||||||
|
// .build();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//}
|
||||||
|
//
|
||||||
@@ -0,0 +1,289 @@
|
|||||||
|
package com.m2pool.lease.config;
|
||||||
|
|
||||||
|
|
||||||
|
import org.springframework.amqp.core.*;
|
||||||
|
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
|
||||||
|
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
|
||||||
|
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||||
|
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
|
||||||
|
import org.springframework.amqp.support.converter.MessageConverter;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static com.m2pool.lease.constant.RabbitmqConstant.*;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class RabbitMQConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public MessageConverter jackson2JsonMessageConverter() {
|
||||||
|
//自动生成消息唯一id
|
||||||
|
//jackson2JsonMessageConverter.setCreateMessageIds(true);
|
||||||
|
return new JacksonMessageConverter();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
|
||||||
|
RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
|
||||||
|
rabbitTemplate.setMessageConverter(jackson2JsonMessageConverter());
|
||||||
|
|
||||||
|
//// 自定义 MessagePostProcessor 来设置 content-type
|
||||||
|
//rabbitTemplate.setBeforePublishPostProcessors(new MessagePostProcessor() {
|
||||||
|
// @Override
|
||||||
|
// public Message postProcessMessage(Message message) {
|
||||||
|
// // 设置 content-type 为 application/json
|
||||||
|
// message.getMessageProperties().setContentType("application/json");
|
||||||
|
// return message;
|
||||||
|
// }
|
||||||
|
//});
|
||||||
|
// 开启发布确认模式
|
||||||
|
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
|
||||||
|
if (ack) {
|
||||||
|
System.out.println("消息发送成功,correlationData: " + correlationData);
|
||||||
|
} else {
|
||||||
|
System.out.println("消息发送失败,原因: " + cause);
|
||||||
|
// 这里可以添加将失败消息存储到数据库的逻辑
|
||||||
|
}
|
||||||
|
});
|
||||||
|
rabbitTemplate.setMandatory(true);
|
||||||
|
return rabbitTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory) {
|
||||||
|
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
|
||||||
|
factory.setConnectionFactory(connectionFactory);
|
||||||
|
//消费者序列化
|
||||||
|
factory.setMessageConverter(jackson2JsonMessageConverter());
|
||||||
|
factory.setConcurrentConsumers(3); // 设置初始消费者数量
|
||||||
|
factory.setMaxConcurrentConsumers(5); // 设置最大消费者数量
|
||||||
|
return factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 矿池代理队列
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Queue poolProxyQueue() {
|
||||||
|
// durable 设置为 true 表示队列持久化
|
||||||
|
return new Queue(POOL_PROXY_QUEUE_NAME, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------定义订单延迟队列------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 死信 交换机
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public DirectExchange deadLetterExchange() {
|
||||||
|
return new DirectExchange(DEAD_LETTER_EXCHANGE_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 死信 队列
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Queue deadLetterQueue() {
|
||||||
|
return new Queue(DEAD_LETTER_QUEUE_NAME, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 死信 队列绑定死信交换机
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Binding deadLetterBinding() {
|
||||||
|
return BindingBuilder.bind(deadLetterQueue()).to(deadLetterExchange()).with(DEAD_LETTER_ROUTING_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单超时消息 交换机
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public DirectExchange orderOvertimeExchange() {
|
||||||
|
return new DirectExchange(ORDER_OVERTIME_EXCHANGE_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单超时消息 队列 (死信交换机达成延迟队列功能)
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Queue orderOvertimeQueue() {
|
||||||
|
Map<String, Object> args = new HashMap<>();
|
||||||
|
// 设置死信交换机
|
||||||
|
args.put("x-dead-letter-exchange", DEAD_LETTER_EXCHANGE_NAME);
|
||||||
|
// 设置死信路由键
|
||||||
|
args.put("x-dead-letter-routing-key", DEAD_LETTER_ROUTING_KEY);
|
||||||
|
// 设置队列中消息的 TTL(单位:毫秒)
|
||||||
|
args.put("x-message-ttl", 900000);
|
||||||
|
return new Queue(ORDER_OVERTIME_QUEUE_NAME, true, false, false, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单超时消息 队列绑定普通交换机
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Binding orderOvertimeBinding() {
|
||||||
|
return BindingBuilder.bind(orderOvertimeQueue()).to(orderOvertimeExchange()).with(ORDER_OVERTIME_ROUTING_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------定义订单延迟队列------------------------
|
||||||
|
|
||||||
|
//----------------定义支付相关队列------------------------
|
||||||
|
/**
|
||||||
|
* 声明 Topic 类型的交换机
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public DirectExchange payExchange() {
|
||||||
|
return new DirectExchange(PAY_EXCHANGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 支付相关队列声明
|
||||||
|
/**
|
||||||
|
* 声明支付消息队列
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Queue payAutoQueue() {
|
||||||
|
return new Queue(PAY_AUTO_QUEUE, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 声明支付返回消息队列
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Queue payAutoReturnQueue() {
|
||||||
|
return new Queue(PAY_AUTO_RETURN_QUEUE, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 余额充值相关队列声明
|
||||||
|
/**
|
||||||
|
* 声明余额充值消息队列
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Queue payRechargeQueue() {
|
||||||
|
return new Queue(PAY_RECHARGE_QUEUE, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 声明余额充值返回信息队列
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Queue payRechargeReturnQueue() {
|
||||||
|
return new Queue(PAY_RECHARGE_RETURN_QUEUE, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 余额提现相关队列声明
|
||||||
|
/**
|
||||||
|
* 声明余额提现消息队列
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Queue payWithdrawQueue() {
|
||||||
|
return new Queue(PAY_WITHDRAW_QUEUE, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 声明余额提现返回信息队列
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Queue payWithdrawReturnQueue() {
|
||||||
|
return new Queue(PAY_WITHDRAW_RETURN_QUEUE, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 支付相关绑定
|
||||||
|
/**
|
||||||
|
* 将支付消息队列绑定到交换机
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Binding payAutoBinding() {
|
||||||
|
return BindingBuilder.bind(payAutoQueue()).to(payExchange()).with(PAY_AUTO_ROUTING_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将支付返回消息队列绑定到交换机
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Binding payAutoReturnBinding() {
|
||||||
|
return BindingBuilder.bind(payAutoReturnQueue()).to(payExchange()).with(PAY_AUTO_RETURN_ROUTING_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 余额充值相关绑定
|
||||||
|
/**
|
||||||
|
* 将余额充值消息队列绑定到交换机
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Binding payRechargeBinding() {
|
||||||
|
return BindingBuilder.bind(payRechargeQueue()).to(payExchange()).with(PAY_RECHARGE_ROUTING_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将余额充值返回信息队列绑定到交换机
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Binding payRechargeReturnBinding() {
|
||||||
|
return BindingBuilder.bind(payRechargeReturnQueue()).to(payExchange()).with(PAY_RECHARGE_RETURN_ROUTING_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 余额提现相关绑定
|
||||||
|
/**
|
||||||
|
* 将余额提现消息队列绑定到交换机
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Binding payWithdrawBinding() {
|
||||||
|
return BindingBuilder.bind(payWithdrawQueue()).to(payExchange()).with(PAY_WITHDRAW_ROUTING_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将余额提现返回信息队列绑定到交换机
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Binding payWithdrawReturnBinding() {
|
||||||
|
return BindingBuilder.bind(payWithdrawReturnQueue()).to(payExchange()).with(PAY_WITHDRAW_RETURN_ROUTING_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//钱包删除 提现相关绑定
|
||||||
|
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Queue deleteWalletReturnQueue() {
|
||||||
|
return new Queue(DELETE_WALLET_RETURN_QUEUE, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Queue deleteWalletQueue() {
|
||||||
|
return new Queue(DELETE_WALLET_QUEUE, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将钱包删除消息队列绑定到交换机
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Binding deleteWalletBinding() {
|
||||||
|
return BindingBuilder.bind(deleteWalletQueue()).to(payExchange()).with(DELETE_WALLET_ROUTING_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将钱包删除返回信息队列绑定到交换机
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Binding deleteWalletReturnBinding() {
|
||||||
|
return BindingBuilder.bind(deleteWalletReturnQueue()).to(payExchange()).with(DELETE_WALLET_RETURN_ROUTING_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//----------------定义支付相关队列------------------------
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.m2pool.lease.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||||
|
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class ThreadPoolConfig {
|
||||||
|
|
||||||
|
@Bean(name = "customThreadPool")
|
||||||
|
public ThreadPoolTaskExecutor customTaskThreadPool() {
|
||||||
|
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||||
|
// 核心线程数
|
||||||
|
executor.setCorePoolSize(5);
|
||||||
|
// 最大线程数
|
||||||
|
executor.setMaxPoolSize(10);
|
||||||
|
// 队列容量
|
||||||
|
executor.setQueueCapacity(50);
|
||||||
|
// 线程空闲时间(秒)
|
||||||
|
executor.setKeepAliveSeconds(30);
|
||||||
|
// 线程名前缀
|
||||||
|
executor.setThreadNamePrefix("custom-task-thread-");
|
||||||
|
// 拒绝策略
|
||||||
|
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
|
||||||
|
// 初始化
|
||||||
|
executor.initialize();
|
||||||
|
return executor;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
//package com.m2pool.lease.config;
|
||||||
|
//
|
||||||
|
//import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
//import org.springframework.context.annotation.Configuration;
|
||||||
|
//import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||||
|
//import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
//
|
||||||
|
//@Configuration
|
||||||
|
//public class WebMvcConfig implements WebMvcConfigurer {
|
||||||
|
//
|
||||||
|
// @Autowired
|
||||||
|
// private AuthInterceptor authInterceptor;
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public void addInterceptors(InterceptorRegistry registry) {
|
||||||
|
// // 注册拦截器并指定拦截路径
|
||||||
|
// registry.addInterceptor(authInterceptor)
|
||||||
|
// .addPathPatterns("/**") // 拦截所有请求
|
||||||
|
// .excludePathPatterns("/login", "/register") // 可选:排除不需要拦截的路径
|
||||||
|
// .excludePathPatterns("/swagger-ui.html", "/webjars/**", "/v2/api-docs", "/swagger-resources/**"); // 可选:排除Swagger相关路径
|
||||||
|
// }
|
||||||
|
//}
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
package com.m2pool.lease.constant;
|
||||||
|
|
||||||
|
import com.m2pool.common.core.utils.StringUtils;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description 币种算法
|
||||||
|
* @Date 2025/8/18 16:19
|
||||||
|
* @Author yyb
|
||||||
|
*/
|
||||||
|
public class Algorithm {
|
||||||
|
// GRS 出块间隔时间单位s
|
||||||
|
public static final String GRS_ALGORITHM= "groestl";
|
||||||
|
// Mona 出块间隔时间单位s
|
||||||
|
public static final String MONA_ALGORITHM= "Lyra2REv2";
|
||||||
|
// NEXA 出块间隔时间单位s
|
||||||
|
public static final String NEXA_ALGORITHM= "NexaPow";
|
||||||
|
// RXD 出块间隔时间单位s
|
||||||
|
public static final String RXD_ALGORITHM= "Sha512256D";
|
||||||
|
|
||||||
|
public static final String DGBQ_ALGORITHM= "DigiByte(Qubit)";
|
||||||
|
|
||||||
|
public static final String DGBS_ALGORITHM= "DigiByte(Skein)";
|
||||||
|
|
||||||
|
public static final String DGBO_ALGORITHM= "DigiByte(Odocrypt)";
|
||||||
|
|
||||||
|
public static final String MONERO_ALGORITHM= "randomx";
|
||||||
|
|
||||||
|
public static final String ALPH_ALGORITHM= "Blake3";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static final String GRS_FULL_NAME= "Groestlcoin";
|
||||||
|
|
||||||
|
public static final String MONA_FULL_NAME= "Monacoin";
|
||||||
|
|
||||||
|
public static final String NEXA_FULL_NAME= "nexa";
|
||||||
|
|
||||||
|
public static final String RXD_FULL_NAME= "Radiant";
|
||||||
|
|
||||||
|
public static final String DGBQ_FULL_NAME= "DigiByte(qubit)";
|
||||||
|
|
||||||
|
public static final String DGBS_FULL_NAME= "DigiByte(skein)";
|
||||||
|
|
||||||
|
public static final String DGBO_FULL_NAME= "DigiByte(odocrypt)";
|
||||||
|
|
||||||
|
public static final String MONERO_FULL_NAME= "monero";
|
||||||
|
|
||||||
|
public static final String ALPH_FULL_NAME = "Alephium";
|
||||||
|
|
||||||
|
private static final Map<String, String> ALGORITHM_MAP;
|
||||||
|
|
||||||
|
private static final Map<String, String> COINFLULLNAME_MAP;
|
||||||
|
|
||||||
|
|
||||||
|
static {
|
||||||
|
HashMap<String, String> map = new HashMap<>();
|
||||||
|
map.put("grs", GRS_ALGORITHM);
|
||||||
|
map.put("mona", MONA_ALGORITHM);
|
||||||
|
map.put("nexa", NEXA_ALGORITHM);
|
||||||
|
map.put("rxd", RXD_ALGORITHM);
|
||||||
|
map.put("dgbq", DGBQ_ALGORITHM);
|
||||||
|
map.put("dgbs", DGBS_ALGORITHM);
|
||||||
|
map.put("dgbo", DGBO_ALGORITHM);
|
||||||
|
map.put("monero", MONERO_ALGORITHM);
|
||||||
|
map.put("alph", ALPH_ALGORITHM);
|
||||||
|
ALGORITHM_MAP = Collections.unmodifiableMap(map);
|
||||||
|
HashMap<String, String> mapFullName = new HashMap<>();
|
||||||
|
mapFullName.put("grs", GRS_FULL_NAME);
|
||||||
|
mapFullName.put("mona", MONA_FULL_NAME);
|
||||||
|
mapFullName.put("nexa", NEXA_FULL_NAME);
|
||||||
|
mapFullName.put("rxd", RXD_FULL_NAME);
|
||||||
|
mapFullName.put("dgbq", DGBQ_FULL_NAME);
|
||||||
|
mapFullName.put("dgbs", DGBS_FULL_NAME);
|
||||||
|
mapFullName.put("dgbo", DGBO_FULL_NAME);
|
||||||
|
mapFullName.put("monero", MONERO_FULL_NAME);
|
||||||
|
mapFullName.put("alph", ALPH_FULL_NAME);
|
||||||
|
COINFLULLNAME_MAP = Collections.unmodifiableMap(mapFullName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据币种名称获取对应的算法
|
||||||
|
* @param coinName 币种名称,不区分大小写
|
||||||
|
* @return 对应的每日理论出块数,如果未找到则返回 null
|
||||||
|
*/
|
||||||
|
public static String getAlgorithm(String coinName) {
|
||||||
|
String algorithm = ALGORITHM_MAP.get(coinName.toLowerCase());
|
||||||
|
if (StringUtils.isEmpty(algorithm)){
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return algorithm;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static String getCoinFullName(String coinName) {
|
||||||
|
String algorithm = COINFLULLNAME_MAP.get(coinName.toLowerCase());
|
||||||
|
if (StringUtils.isEmpty(algorithm)){
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return algorithm;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package com.m2pool.lease.constant;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description 出块间隔数
|
||||||
|
* @Date 2025/8/18 16:19
|
||||||
|
* @Author yyb
|
||||||
|
*/
|
||||||
|
public class BlockInterval {
|
||||||
|
// GRS 出块间隔时间单位s
|
||||||
|
public static final BigDecimal GRS_BLOCK_INTERVAL = BigDecimal.valueOf(60);
|
||||||
|
// Mona 出块间隔时间单位s
|
||||||
|
public static final BigDecimal MONA_BLOCK_INTERVAL = BigDecimal.valueOf(90);
|
||||||
|
// NEXA 出块间隔时间单位s
|
||||||
|
public static final BigDecimal NEXA_BLOCK_INTERVAL = BigDecimal.valueOf(120);
|
||||||
|
// RXD 出块间隔时间单位s
|
||||||
|
public static final BigDecimal RXD_BLOCK_INTERVAL= BigDecimal.valueOf(300);
|
||||||
|
|
||||||
|
private static final Map<String, BigDecimal> BLOCK_MAP;
|
||||||
|
|
||||||
|
static {
|
||||||
|
HashMap<String, BigDecimal> map = new HashMap<>();
|
||||||
|
map.put("grs", GRS_BLOCK_INTERVAL);
|
||||||
|
map.put("mona", MONA_BLOCK_INTERVAL);
|
||||||
|
map.put("nexa", NEXA_BLOCK_INTERVAL);
|
||||||
|
map.put("rxd", RXD_BLOCK_INTERVAL);
|
||||||
|
BLOCK_MAP = Collections.unmodifiableMap(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据币种名称获取对应的每日理论出块数
|
||||||
|
* @param coinName 币种名称,不区分大小写
|
||||||
|
* @return 对应的每日理论出块数,如果未找到则返回 null
|
||||||
|
*/
|
||||||
|
public static BigDecimal getBlockCountByCoinName(String coinName) {
|
||||||
|
if (coinName == null) {
|
||||||
|
return BigDecimal.ZERO;
|
||||||
|
}
|
||||||
|
return BLOCK_MAP.get(coinName.toLowerCase());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
package com.m2pool.lease.constant;
|
||||||
|
|
||||||
|
import com.m2pool.lease.dto.ChargeDto;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description 币种手续费
|
||||||
|
* @Date 2025/10/23 11:15
|
||||||
|
* @Author yyb
|
||||||
|
*/
|
||||||
|
public enum CoinCharge {
|
||||||
|
|
||||||
|
ETH_USDT("ETH","USDT", BigDecimal.valueOf(1)),
|
||||||
|
TRON_USDT("TRON","USDT", BigDecimal.valueOf(1)),
|
||||||
|
TRON_NEXA("TRON","NEXA", BigDecimal.valueOf(1000));
|
||||||
|
|
||||||
|
private final String chain;
|
||||||
|
/** 币种参数名 */
|
||||||
|
private final String coin;
|
||||||
|
/** 手续费 */
|
||||||
|
private final BigDecimal amount;
|
||||||
|
|
||||||
|
|
||||||
|
CoinCharge(String chain, String coin, BigDecimal amount) {
|
||||||
|
this.chain = chain;
|
||||||
|
this.coin = coin;
|
||||||
|
this.amount = amount;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 根据 chain 和 coin 查找对应的手续费,未找到则返回 1
|
||||||
|
* @param chain 链名
|
||||||
|
* @param coin 币种名
|
||||||
|
* @return 对应的手续费,未找到返回 1
|
||||||
|
*/
|
||||||
|
public static BigDecimal getChargeByChainAndCoin(String chain, String coin) {
|
||||||
|
for (CoinCharge charge : CoinCharge.values()) {
|
||||||
|
if (charge.chain.equals(chain) && charge.coin.equals(coin)) {
|
||||||
|
return charge.amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return BigDecimal.ONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取枚举类中所有枚举,并封装成 List<ChargeDto>
|
||||||
|
* @return 包含所有枚举信息的 ChargeDto 列表
|
||||||
|
*/
|
||||||
|
public static List<ChargeDto> getAllChargesAsDtoList() {
|
||||||
|
List<ChargeDto> chargeDtoList = new ArrayList<>();
|
||||||
|
for (CoinCharge charge : CoinCharge.values()) {
|
||||||
|
chargeDtoList.add(new ChargeDto(
|
||||||
|
charge.amount,
|
||||||
|
charge.chain,
|
||||||
|
charge.coin
|
||||||
|
));
|
||||||
|
}
|
||||||
|
return chargeDtoList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
package com.m2pool.lease.constant;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class DailyBlockOutputConstant {
|
||||||
|
// GRS 每日理论出块数常量
|
||||||
|
public static final BigDecimal GRS_BLOCK = BigDecimal.valueOf(1440);
|
||||||
|
// Mona 每日理论出块数常量
|
||||||
|
public static final BigDecimal MONA_BLOCK = BigDecimal.valueOf(960);
|
||||||
|
// DGBS 每日理论出块数常量
|
||||||
|
public static final BigDecimal DGBS_BLOCK = BigDecimal.valueOf(1180);
|
||||||
|
// DGBQ 每日理论出块数常量
|
||||||
|
public static final BigDecimal DGBQ_BLOCK = BigDecimal.valueOf(1180);
|
||||||
|
// DGBO 每日理论出块数常量
|
||||||
|
public static final BigDecimal DGBO_BLOCK = BigDecimal.valueOf(1180);
|
||||||
|
// DGB2_ODO 每日理论出块数常量
|
||||||
|
public static final BigDecimal DGB2_ODO_BLOCK = BigDecimal.valueOf(720);
|
||||||
|
// DGB_QUBIT_A10 每日理论出块数常量
|
||||||
|
public static final BigDecimal DGB_QUBIT_A10_BLOCK = BigDecimal.valueOf(720);
|
||||||
|
// DGB_SKEIN_A10 每日理论出块数常量
|
||||||
|
public static final BigDecimal DGB_SKEIN_A10_BLOCK = BigDecimal.valueOf(720);
|
||||||
|
// DGB_ODO_B20 每日理论出块数常量
|
||||||
|
public static final BigDecimal DGB_ODO_B20_BLOCK = BigDecimal.valueOf(720);
|
||||||
|
// NEXA 每日理论出块数常量
|
||||||
|
public static final BigDecimal NEXA_BLOCK = BigDecimal.valueOf(720);
|
||||||
|
// RXD 每日理论出块数常量
|
||||||
|
public static final BigDecimal RXD_BLOCK = BigDecimal.valueOf(288);
|
||||||
|
// ALPH 每日理论出块数常量
|
||||||
|
public static final BigDecimal ALPH_BLOCK = BigDecimal.valueOf(5400);
|
||||||
|
// ENX 每日理论出块数常量
|
||||||
|
public static final BigDecimal ENX_BLOCK = BigDecimal.valueOf(86400);
|
||||||
|
|
||||||
|
private static final Map<String, BigDecimal> BLOCK_MAP;
|
||||||
|
|
||||||
|
static {
|
||||||
|
BLOCK_MAP = new HashMap<>();
|
||||||
|
BLOCK_MAP.put("grs", GRS_BLOCK);
|
||||||
|
BLOCK_MAP.put("mona", MONA_BLOCK);
|
||||||
|
BLOCK_MAP.put("dgbs", DGBS_BLOCK);
|
||||||
|
BLOCK_MAP.put("dgbq", DGBQ_BLOCK);
|
||||||
|
BLOCK_MAP.put("dgbo", DGBO_BLOCK);
|
||||||
|
BLOCK_MAP.put("dgb2_odo", DGB2_ODO_BLOCK);
|
||||||
|
BLOCK_MAP.put("dgb_qubit_a10", DGB_QUBIT_A10_BLOCK);
|
||||||
|
BLOCK_MAP.put("dgb_skein_a10", DGB_SKEIN_A10_BLOCK);
|
||||||
|
BLOCK_MAP.put("dgb_odo_b20", DGB_ODO_B20_BLOCK);
|
||||||
|
BLOCK_MAP.put("nexa", NEXA_BLOCK);
|
||||||
|
BLOCK_MAP.put("rxd", RXD_BLOCK);
|
||||||
|
BLOCK_MAP.put("alph", ALPH_BLOCK);
|
||||||
|
BLOCK_MAP.put("enx", ENX_BLOCK);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据币种名称获取对应的每日理论出块数
|
||||||
|
* @param coinName 币种名称,不区分大小写
|
||||||
|
* @return 对应的每日理论出块数,如果未找到则返回 null
|
||||||
|
*/
|
||||||
|
public static BigDecimal getBlockCountByCoinName(String coinName) {
|
||||||
|
if (coinName == null) {
|
||||||
|
return BigDecimal.ZERO;
|
||||||
|
}
|
||||||
|
return BLOCK_MAP.get(coinName.toLowerCase());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package com.m2pool.lease.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description 普通订单状态
|
||||||
|
* @Date 2025/9/3 16:19
|
||||||
|
* @Author yyb
|
||||||
|
*/
|
||||||
|
public enum OrderStatus {
|
||||||
|
PENDING_PAYMENT(0, "待支付"),
|
||||||
|
FULLY_PAID(1, "(全部)已支付"),
|
||||||
|
CANCELLED(2, "已取消"),
|
||||||
|
AFTER_SALES(3, "售后状态"),
|
||||||
|
REFUNDED(4, "已退款"),
|
||||||
|
PAYMENT_TIMEOUT(5, "支付已超时"),
|
||||||
|
PAYMENT_IN_PROGRESS(6, "支付中"),
|
||||||
|
PARTIALLY_PAID(10, "部分已支付");
|
||||||
|
|
||||||
|
private final int code;
|
||||||
|
private final String description;
|
||||||
|
|
||||||
|
OrderStatus(int code, String description) {
|
||||||
|
this.code = code;
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取订单状态编码
|
||||||
|
* @return 订单状态编码
|
||||||
|
*/
|
||||||
|
public int getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取订单状态描述
|
||||||
|
* @return 订单状态描述
|
||||||
|
*/
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据编码获取对应的订单状态枚举
|
||||||
|
* @param code 订单状态编码
|
||||||
|
* @return 订单状态枚举,如果未找到则返回 null
|
||||||
|
*/
|
||||||
|
public static OrderStatus getByCode(int code) {
|
||||||
|
for (OrderStatus status : OrderStatus.values()) {
|
||||||
|
if (status.getCode() == code) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package com.m2pool.lease.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description 支付订单状态
|
||||||
|
* @Date 2025/9/3 16:19
|
||||||
|
* @Author yyb
|
||||||
|
*/
|
||||||
|
public enum PaymentStatus {
|
||||||
|
PAYMENT_FAILED(0, "支付失败"),
|
||||||
|
PAYMENT_SUCCESS_FULL(1, "支付成功--全部货款已支付"),
|
||||||
|
PENDING_PAYMENT(2, "待支付"),
|
||||||
|
PAYMENT_TIMEOUT(5, "支付已超时"),
|
||||||
|
PAYMENT_IN_PROGRESS(6, "支付中"),
|
||||||
|
PAYMENT_SUCCESS_PARTIAL(10, "支付成功--已支付部分货款");
|
||||||
|
|
||||||
|
private final int code;
|
||||||
|
private final String description;
|
||||||
|
|
||||||
|
PaymentStatus(int code, String description) {
|
||||||
|
this.code = code;
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取支付状态编码
|
||||||
|
* @return 支付状态编码
|
||||||
|
*/
|
||||||
|
public int getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取支付状态描述
|
||||||
|
* @return 支付状态描述
|
||||||
|
*/
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据编码获取对应的支付状态枚举
|
||||||
|
* @param code 支付状态编码
|
||||||
|
* @return 支付状态枚举,如果未找到则返回 null
|
||||||
|
*/
|
||||||
|
public static PaymentStatus getByCode(int code) {
|
||||||
|
for (PaymentStatus status : PaymentStatus.values()) {
|
||||||
|
if (status.getCode() == code) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package com.m2pool.lease.constant;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description 单位换算
|
||||||
|
* @Date 2025/8/18 16:19
|
||||||
|
* @Author yyb
|
||||||
|
*/
|
||||||
|
public class PowerUnit {
|
||||||
|
|
||||||
|
public static final String KH_UNIT = "KH/S";
|
||||||
|
|
||||||
|
public static final String MH_UNIT = "MH/S";
|
||||||
|
|
||||||
|
public static final String GH_UNIT = "GH/S";
|
||||||
|
|
||||||
|
public static final String TH_UNIT = "TH/S";
|
||||||
|
|
||||||
|
public static final String PH_UNIT = "PH/S";
|
||||||
|
|
||||||
|
private static final Map<String, BigDecimal> UNIT_MAP;
|
||||||
|
|
||||||
|
static {
|
||||||
|
HashMap<String, BigDecimal> map = new HashMap<>();
|
||||||
|
map.put(KH_UNIT, BigDecimal.valueOf(1000));
|
||||||
|
map.put(MH_UNIT, BigDecimal.valueOf(1000 * 1000));
|
||||||
|
map.put(GH_UNIT, BigDecimal.valueOf(1000L * 1000 * 1000 * 1000));
|
||||||
|
map.put(TH_UNIT, BigDecimal.valueOf(1000L * 1000 * 1000 * 1000 * 1000));
|
||||||
|
map.put(PH_UNIT, BigDecimal.valueOf(1000L * 1000 * 1000 * 1000 * 1000 * 1000));
|
||||||
|
UNIT_MAP = Collections.unmodifiableMap(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static BigDecimal getPower(String unit) {
|
||||||
|
if (unit == null) {
|
||||||
|
return BigDecimal.ZERO;
|
||||||
|
}
|
||||||
|
return UNIT_MAP.get(unit);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,156 @@
|
|||||||
|
package com.m2pool.lease.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description 常量信息
|
||||||
|
* @Date 2024/6/11 18:13
|
||||||
|
* @Author dy
|
||||||
|
*/
|
||||||
|
public class RabbitmqConstant {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 矿池代理消息队列
|
||||||
|
*/
|
||||||
|
public static final String POOL_PROXY_QUEUE_NAME = "pool.proxy.queue";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 矿池代理消息correlationData(用于生成者手动ack)
|
||||||
|
*/
|
||||||
|
public static final String POOL_PROXY_CORRELATION = "pool.proxy.message";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单超时消息 交换机
|
||||||
|
*/
|
||||||
|
public static final String ORDER_OVERTIME_EXCHANGE_NAME = "order.overtime.exchange";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单超时消息 路由键
|
||||||
|
*/
|
||||||
|
public static final String ORDER_OVERTIME_ROUTING_KEY = "order.overtime.routing.key";
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 订单超时消息 队列
|
||||||
|
*/
|
||||||
|
public static final String ORDER_OVERTIME_QUEUE_NAME = "order.overtime.queue";
|
||||||
|
/**
|
||||||
|
* 订单超时消息correlationData(用于生成者手动ack)
|
||||||
|
*/
|
||||||
|
public static final String ORDER_OVERTIME_CORRELATION= "order.overtime.message";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 死信 队列
|
||||||
|
*/
|
||||||
|
public static final String DEAD_LETTER_QUEUE_NAME = "dead.letter.queue";
|
||||||
|
/**
|
||||||
|
* 死信 交换机
|
||||||
|
*/
|
||||||
|
public static final String DEAD_LETTER_EXCHANGE_NAME = "dead.letter.exchange";
|
||||||
|
/**
|
||||||
|
* 死信 路由键
|
||||||
|
*/
|
||||||
|
public static final String DEAD_LETTER_ROUTING_KEY = "dead.letter.routing.key";
|
||||||
|
|
||||||
|
|
||||||
|
//----------------定义支付相关队列------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付模块 交换机
|
||||||
|
*/
|
||||||
|
public static final String PAY_EXCHANGE = "pay.exchange";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付 消息队列
|
||||||
|
*/
|
||||||
|
public static final String PAY_AUTO_QUEUE = "pay.auto.queue";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付 路由键
|
||||||
|
*/
|
||||||
|
public static final String PAY_AUTO_ROUTING_KEY = "pay.auto.routing.key";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付 返回消息消息队列
|
||||||
|
*/
|
||||||
|
public static final String PAY_AUTO_RETURN_QUEUE = "pay.auto.return.queue";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付 返回消息路由键
|
||||||
|
*/
|
||||||
|
public static final String PAY_AUTO_RETURN_ROUTING_KEY = "pay.auto.return.routing.key";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 余额充值 消息队列
|
||||||
|
*/
|
||||||
|
public static final String PAY_RECHARGE_QUEUE = "pay.recharge.queue";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 余额充值 路由键
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static final String PAY_RECHARGE_ROUTING_KEY = "pay.recharge.routing.key";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 余额充值 返回信息消息队列
|
||||||
|
*/
|
||||||
|
public static final String PAY_RECHARGE_RETURN_QUEUE = "pay.recharge.return.queue";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 余额充值 返回信息路由键
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static final String PAY_RECHARGE_RETURN_ROUTING_KEY = "pay.recharge.return.routing.key";
|
||||||
|
/**
|
||||||
|
* 余额提现 消息队列
|
||||||
|
*/
|
||||||
|
public static final String PAY_WITHDRAW_QUEUE = "pay.withdraw.queue";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 余额提现 路由键
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static final String PAY_WITHDRAW_ROUTING_KEY = "pay.withdraw.routing.key";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 余额提现 返回信息消息队列
|
||||||
|
*/
|
||||||
|
public static final String PAY_WITHDRAW_RETURN_QUEUE = "pay.withdraw.return.queue";
|
||||||
|
/**
|
||||||
|
* 余额提现 返回信息路由键
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static final String PAY_WITHDRAW_RETURN_ROUTING_KEY = "pay.withdraw.return.routing.key";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 钱包删除 信息消息队列
|
||||||
|
*/
|
||||||
|
public static final String DELETE_WALLET_QUEUE = "pay.remove.queue";
|
||||||
|
/**
|
||||||
|
* 钱包删除 信息路由键
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static final String DELETE_WALLET_ROUTING_KEY = "pay.remove.routing.key";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 钱包删除 返回信息消息队列
|
||||||
|
*/
|
||||||
|
public static final String DELETE_WALLET_RETURN_QUEUE = "pay.remove.return.queue";
|
||||||
|
/**
|
||||||
|
* 钱包删除 返回信息路由键
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static final String DELETE_WALLET_RETURN_ROUTING_KEY = "pay.remove.return.routing.key";
|
||||||
|
|
||||||
|
|
||||||
|
//----------------定义支付相关队列------------------------
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
package com.m2pool.lease.constant;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description redis key
|
||||||
|
* @Date 2025/8/18 09:49
|
||||||
|
* @Author yyb
|
||||||
|
*/
|
||||||
|
public class RedisKey {
|
||||||
|
// 静态不可变的 Map,存储币种名和对应价格标识
|
||||||
|
private static final Map<String, String> COIN_PRICE_MAP;
|
||||||
|
|
||||||
|
private static final Map<String, String> COIN_MHS_MAP;
|
||||||
|
|
||||||
|
private static final Map<String, String> COIN_REWARD_MAP;
|
||||||
|
static {
|
||||||
|
|
||||||
|
Map<String, String> mapPrice = new HashMap<>();
|
||||||
|
mapPrice.put("nexa", "nexa:price");
|
||||||
|
mapPrice.put("mona", "mona:price");
|
||||||
|
mapPrice.put("rxd", "rxd:price");
|
||||||
|
mapPrice.put("grs", "grs:price");
|
||||||
|
mapPrice.put("dgbs","dgb:price");
|
||||||
|
mapPrice.put("dgbq","dgb:price");
|
||||||
|
mapPrice.put("dgbo","dgb:price");
|
||||||
|
mapPrice.put("alph","alph:price");
|
||||||
|
mapPrice.put("eth","eth:price");
|
||||||
|
|
||||||
|
Map<String, String> mapMhs = new HashMap<>();
|
||||||
|
mapMhs.put("nexa", "nexa:mhs");
|
||||||
|
mapMhs.put("mona", "mona:mhs");
|
||||||
|
mapMhs.put("rxd", "rxd:mhs");
|
||||||
|
mapMhs.put("grs", "grs:mhs");
|
||||||
|
mapMhs.put("dgbo","dgbo:mhs");
|
||||||
|
mapMhs.put("dgbq","dgbq:mhs");
|
||||||
|
mapMhs.put("dgbs","dgbs:mhs");
|
||||||
|
mapMhs.put("alph","alph:mhs");
|
||||||
|
|
||||||
|
|
||||||
|
Map<String, String> mapReward = new HashMap<>();
|
||||||
|
mapReward.put("nexa", "nexa:reward");
|
||||||
|
mapReward.put("mona", "mona:reward");
|
||||||
|
mapReward.put("rxd", "rxd:reward");
|
||||||
|
mapReward.put("grs", "grs:reward");
|
||||||
|
mapReward.put("dgbs","dgb:reward");
|
||||||
|
mapReward.put("dgbq","dgb:reward");
|
||||||
|
mapReward.put("dgbo","dgb:reward");
|
||||||
|
mapReward.put("alph","alph:reward");
|
||||||
|
COIN_PRICE_MAP = Collections.unmodifiableMap(mapPrice);
|
||||||
|
COIN_MHS_MAP = Collections.unmodifiableMap(mapMhs);
|
||||||
|
COIN_REWARD_MAP = Collections.unmodifiableMap(mapReward);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据币种名获取对应的价格标识
|
||||||
|
* @param coinName 币种名
|
||||||
|
* @return 对应的价格标识,若不存在则返回 null
|
||||||
|
*/
|
||||||
|
public static String getPiceKey(String coinName) {
|
||||||
|
return COIN_PRICE_MAP.get(coinName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getMhsKey(String coinName) {
|
||||||
|
return COIN_MHS_MAP.get(coinName);
|
||||||
|
}
|
||||||
|
public static String getRewardKey(String coinName) {
|
||||||
|
return COIN_REWARD_MAP.get(coinName);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
package com.m2pool.lease.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description 常量信息
|
||||||
|
* @Date 2024/6/11 18:13
|
||||||
|
* @Author dy
|
||||||
|
*/
|
||||||
|
public class ResponseConstant {
|
||||||
|
/**
|
||||||
|
* 成功标记
|
||||||
|
*/
|
||||||
|
public static final Integer SUCCESS = 200;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 失败标记
|
||||||
|
*/
|
||||||
|
public static final Integer FAIL = 500;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录成功状态
|
||||||
|
*/
|
||||||
|
public static final String LOGIN_SUCCESS_STATUS = "0";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录失败状态
|
||||||
|
*/
|
||||||
|
public static final String LOGIN_FAIL_STATUS = "1";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录成功
|
||||||
|
*/
|
||||||
|
public static final String LOGIN_SUCCESS = "Success";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注销
|
||||||
|
*/
|
||||||
|
public static final String LOGOUT = "Logout";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册
|
||||||
|
*/
|
||||||
|
public static final String REGISTER = "Register";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录失败
|
||||||
|
*/
|
||||||
|
public static final String LOGIN_FAIL = "Error";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前记录起始索引
|
||||||
|
*/
|
||||||
|
public static final String PAGE_NUM = "pageNum";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每页显示记录数
|
||||||
|
*/
|
||||||
|
public static final String PAGE_SIZE = "pageSize";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排序列
|
||||||
|
*/
|
||||||
|
public static final String ORDER_BY_COLUMN = "orderByColumn";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排序的方向 "desc" 或者 "asc".
|
||||||
|
*/
|
||||||
|
public static final String IS_ASC = "isAsc";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证码 redis key
|
||||||
|
*/
|
||||||
|
public static final String CAPTCHA_CODE_KEY = "captcha_codes:";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证码有效期(分钟)
|
||||||
|
*/
|
||||||
|
public static final long CAPTCHA_EXPIRATION = 2;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 参数管理 cache key
|
||||||
|
*/
|
||||||
|
public static final String SYS_CONFIG_KEY = "sys_config:";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资源映射路径 前缀
|
||||||
|
*/
|
||||||
|
public static final String RESOURCE_PREFIX = "/profile";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.m2pool.lease.controller;
|
||||||
|
|
||||||
|
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 矿池nexa机器实时平均算力 前端控制器
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author yyb
|
||||||
|
* @since 2025-07-29
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/machine/avg/power")
|
||||||
|
public class LeaseMachineAvgPowerController {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.m2pool.lease.controller;
|
||||||
|
|
||||||
|
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 已售商品矿工实时算力表 前端控制器
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author yyb
|
||||||
|
* @since 2025-07-25
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/machine/power")
|
||||||
|
public class LeaseMachinePowerController {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
package com.m2pool.lease.controller;
|
||||||
|
|
||||||
|
|
||||||
|
import com.m2pool.common.security.annotation.RequiresLogin;
|
||||||
|
import com.m2pool.lease.dto.OrderInfoDto;
|
||||||
|
import com.m2pool.lease.dto.PageResult;
|
||||||
|
import com.m2pool.lease.dto.PaymentRecordDto;
|
||||||
|
import com.m2pool.lease.dto.Result;
|
||||||
|
import com.m2pool.lease.service.LeaseOrderInfoService;
|
||||||
|
import com.m2pool.lease.vo.*;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 订单表 前端控制器
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author yyb
|
||||||
|
* @since 2025-07-23
|
||||||
|
*/
|
||||||
|
@Api(tags = "订单控制器")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/order/info")
|
||||||
|
public class LeaseOrderInfoController {
|
||||||
|
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private LeaseOrderInfoService leaseOrderInfoService;
|
||||||
|
|
||||||
|
@ApiOperation("创建订单及订单详情 + 支付订单(返回二维码内容)")
|
||||||
|
@PostMapping("/addOrders")
|
||||||
|
public Result<String> addOrders(@RequestBody OrderAndCodeVo orderAndCodeVo) {
|
||||||
|
return leaseOrderInfoService.addOrders(orderAndCodeVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("订单支付超时--再次购买功能")
|
||||||
|
@PostMapping("/buyAgain")
|
||||||
|
@Deprecated
|
||||||
|
public Result<List<PaymentRecordDto>> buyAgain(@RequestBody List<OrderInfoVo> orderInfoVoList) {
|
||||||
|
return leaseOrderInfoService.buyAgain(orderInfoVoList);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("查询订单列表(买家)")
|
||||||
|
@PostMapping("/getOrdersByStatus")
|
||||||
|
public PageResult<OrderInfoDto> getOrdersByStatus(@RequestBody OrderInfoStateVo orderInfoStateVo) {
|
||||||
|
return leaseOrderInfoService.getOrdersByStatus(orderInfoStateVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ApiOperation("卖家已售出订单列表(卖家)")
|
||||||
|
@PostMapping("/getOrdersByStatusForSeller")
|
||||||
|
public PageResult<OrderInfoDto> getOrdersByStatusForSeller(@RequestBody OrderInfoStateVo orderInfoStateVo) {
|
||||||
|
return leaseOrderInfoService.getOrdersByStatusForSeller(orderInfoStateVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ApiOperation("根据订单id查询订单信息")
|
||||||
|
@PostMapping("/getOrdersByIds")
|
||||||
|
public Result<OrderInfoDto> getOrdersByIds(@RequestBody OrderVo orderVo) {
|
||||||
|
return leaseOrderInfoService.getOrdersByIds(orderVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("取消订单(如果有支付订单同时取消)")
|
||||||
|
@PostMapping("/cancelOrder")
|
||||||
|
public Result<String> cancelOrder(@RequestBody OrderVo orderVo) {
|
||||||
|
return leaseOrderInfoService.cancelOrder(orderVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("生成订单时获取用户选择的支付币种 实时币价")
|
||||||
|
@PostMapping("/getCoinPrice")
|
||||||
|
public Result<BigDecimal> getCoinPrice(@RequestBody CoinVo coinVo){
|
||||||
|
return leaseOrderInfoService.getCoinPrice(coinVo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
package com.m2pool.lease.controller;
|
||||||
|
|
||||||
|
|
||||||
|
import com.m2pool.common.security.annotation.RequiresLogin;
|
||||||
|
import com.m2pool.lease.dto.PaymentCallbackDto;
|
||||||
|
import com.m2pool.lease.dto.PaymentRecordDto;
|
||||||
|
import com.m2pool.lease.dto.Result;
|
||||||
|
import com.m2pool.lease.service.LeasePaymentRecordService;
|
||||||
|
import com.m2pool.lease.vo.CheckPayStatusVo;
|
||||||
|
import com.m2pool.lease.vo.OrderVo;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 支付记录表 前端控制器
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author yyb
|
||||||
|
* @since 2025-07-23
|
||||||
|
*/
|
||||||
|
@Api(tags = "支付记录控制器")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/payment/record")
|
||||||
|
public class LeasePaymentRecordController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private LeasePaymentRecordService leasePaymentRecordService;
|
||||||
|
|
||||||
|
@ApiOperation("根据订单详情信息生成 支付订单 + 根据返回的集合生成多个支付二维码")
|
||||||
|
@PostMapping("/addPayOrder")
|
||||||
|
@Deprecated
|
||||||
|
public Result<List<PaymentRecordDto>> addPayOrder(@RequestBody OrderVo orderVo) {
|
||||||
|
return leasePaymentRecordService.addPayOrder(orderVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ApiOperation("根据订单id找到支付订单")
|
||||||
|
@PostMapping("/getPayOrderByOrderId")
|
||||||
|
public Result<List<PaymentRecordDto>> getPayOrderByOrderId(@RequestBody OrderVo orderVo) {
|
||||||
|
return leasePaymentRecordService.getPayOrderByOrderId(orderVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ApiOperation("支付回调结果---根据订单id批量校验本次支付是否成功")
|
||||||
|
@PostMapping("/paymentCallbackBatch")
|
||||||
|
@Deprecated
|
||||||
|
public Result<List<PaymentCallbackDto>> paymentCallbackBatch(@RequestBody List<CheckPayStatusVo> checkPayStatusVoList) {
|
||||||
|
return leasePaymentRecordService.paymentCallbackBatch(checkPayStatusVoList);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("支付回调结果----根据支付id校验支付是否成功")
|
||||||
|
@PostMapping("/paymentCallbackByPayId")
|
||||||
|
@Deprecated
|
||||||
|
public Result<PaymentCallbackDto> paymentCallbackByPayId(@RequestBody CheckPayStatusVo checkPayStatusVo) {
|
||||||
|
return leasePaymentRecordService.paymentCallbackByPayId(checkPayStatusVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
package com.m2pool.lease.controller;
|
||||||
|
|
||||||
|
|
||||||
|
import com.m2pool.lease.dto.*;
|
||||||
|
import com.m2pool.lease.service.LeaseProductService;
|
||||||
|
import com.m2pool.lease.service.LeaseUserOwnedProductService;
|
||||||
|
import com.m2pool.lease.vo.BaseVo;
|
||||||
|
import com.m2pool.lease.vo.ProductPageVo;
|
||||||
|
import com.m2pool.lease.vo.ProductURDVo;
|
||||||
|
import com.m2pool.lease.vo.UserOwnedProductVo;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 商品表 前端控制器
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author yyb
|
||||||
|
* @since 2025-07-23
|
||||||
|
*/
|
||||||
|
@Api(tags = "商品控制器")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/product")
|
||||||
|
public class LeaseProductController {
|
||||||
|
@Autowired
|
||||||
|
private LeaseProductService leaseProductService;
|
||||||
|
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private LeaseUserOwnedProductService leaseUserOwnedProductService;
|
||||||
|
@ApiOperation("查询商品列表(不包含商品对应的售卖机器详情列表)")
|
||||||
|
@PostMapping("/getList")
|
||||||
|
public PageResult<ProductDto> getProductList(@RequestBody(required = false) ProductPageVo productPageVo) {
|
||||||
|
if (productPageVo == null){
|
||||||
|
productPageVo = new ProductPageVo();
|
||||||
|
}
|
||||||
|
return leaseProductService.getProductList(productPageVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ApiOperation("根据商品id查询单个商品详情信息")
|
||||||
|
@PostMapping("/getMachineInfoById")
|
||||||
|
public Result<ProductDto> getMachineInfoById(@RequestBody BaseVo baseVo) {
|
||||||
|
return leaseProductService.getMachineInfoById(baseVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ApiOperation("查询单个商品详情(包含商品对应的售卖机器详情列表)")
|
||||||
|
@PostMapping("/getMachineInfo")
|
||||||
|
public Result<ProductMachineInfoDto> getProductMachineInfo(@RequestBody BaseVo BaseVo) {
|
||||||
|
return leaseProductService.getProductMachineInfo(BaseVo.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ApiOperation("新增商品(不包含商品对应的售卖机器)")
|
||||||
|
@PostMapping("/add")
|
||||||
|
public Result<String> addProduct(@RequestBody ProductURDVo productURDVo) {
|
||||||
|
return leaseProductService.addProduct(productURDVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("编辑商品 + 商品上下架(不包含商品对应的售卖机器)")
|
||||||
|
@PostMapping("/update")
|
||||||
|
public Result<String> updateProduct(@RequestBody ProductURDVo productURDVo) {
|
||||||
|
return leaseProductService.updateProduct(productURDVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("删除商品(包含商品对应的售卖机器)")
|
||||||
|
@PostMapping("/delete")
|
||||||
|
public Result<String> deleteProduct(@RequestBody BaseVo baseVo) {
|
||||||
|
return leaseProductService.deleteProduct(baseVo.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ApiOperation("用户查询当前自身已购商品列表")
|
||||||
|
@PostMapping("/getOwnedList")
|
||||||
|
public PageResult<UserOwnedProductDto> getOwnedList(@RequestBody(required = false) UserOwnedProductVo userOwnedProductVo) {
|
||||||
|
if (userOwnedProductVo == null){
|
||||||
|
userOwnedProductVo = new UserOwnedProductVo();
|
||||||
|
}
|
||||||
|
return leaseUserOwnedProductService.getOwnedList(userOwnedProductVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ApiOperation("根据id查询当前自身已购商品详情")
|
||||||
|
@PostMapping("/getOwnedById")
|
||||||
|
public Result<UserOwnedProductDto> getOwnedById(@RequestBody BaseVo baseVo) {
|
||||||
|
return leaseUserOwnedProductService.getOwnedById(baseVo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
package com.m2pool.lease.controller;
|
||||||
|
|
||||||
|
|
||||||
|
import com.m2pool.common.security.annotation.RequiresLogin;
|
||||||
|
import com.m2pool.lease.dto.*;
|
||||||
|
import com.m2pool.lease.service.LeaseProductMachineService;
|
||||||
|
import com.m2pool.lease.vo.*;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 商品表对应的物品机器表 前端控制器
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author yyb
|
||||||
|
* @since 2025-07-23
|
||||||
|
*/
|
||||||
|
@Api(tags = "商品矿机控制器(库存控制器)")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/product/machine")
|
||||||
|
public class LeaseProductMachineController {
|
||||||
|
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private LeaseProductMachineService leaseProductMachineService;
|
||||||
|
|
||||||
|
@ApiOperation("根据 登录账户 获取挖矿账户及挖矿币种集合----用于用户为商品添加实际出售机器库存")
|
||||||
|
@PostMapping("/getUserMinersList")
|
||||||
|
public Result<Map<String, List<UserMinerDto>>> getUserMinersList(@RequestBody UserMinerVo userMinerVo) {
|
||||||
|
return leaseProductMachineService.getUserMinersList(userMinerVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("根据挖矿账户获取对应的 矿机机器编码集合----用于用户为商品添加实际出售机器库存")
|
||||||
|
@PostMapping("/getUserMachineList")
|
||||||
|
public Result<List<UserMinerDto>> getUserMachineList(@RequestBody UserMinerVo userMinerVo) {
|
||||||
|
return leaseProductMachineService.getUserMachineList(userMinerVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ApiOperation("根据商品id查询商品矿机列表----用于卖方修改矿机信息")
|
||||||
|
@PostMapping("/getMachineListForUpdate")
|
||||||
|
public PageResult<ProductUpdateMachineDto> getMachineListForUpdate(@RequestBody ProductForUpdateMachineVo productForUpdateMachineVo) {
|
||||||
|
return leaseProductMachineService.getMachineListForUpdate(productForUpdateMachineVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ApiOperation("单个新增或批量新增出售机器")
|
||||||
|
@PostMapping("/addSingleOrBatchMachine")
|
||||||
|
public Result<String> addSingleOrBatchMachine(@RequestBody ProductMachineParamsVo productMachineParamsVoList) {
|
||||||
|
return leaseProductMachineService.addSingleOrBatchMachine(productMachineParamsVoList);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("单个/批量 编辑矿机 + 矿机上下架")
|
||||||
|
@PostMapping("/updateMachine")
|
||||||
|
public Result<String> updateMachine(@RequestBody List<ProductUpdateMachineVo> productUpdateMachineVoList) {
|
||||||
|
return leaseProductMachineService.updateMachine(productUpdateMachineVoList);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("根据矿机id 删除商品矿机")
|
||||||
|
@PostMapping("/delete")
|
||||||
|
public Result<String> deleteMachine(@RequestBody BaseVo baseVo) {
|
||||||
|
return leaseProductMachineService.deleteMachine(baseVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//@ApiOperation("价格计算器---添加机器到商品中时需要给一个价格")
|
||||||
|
//@PostMapping("/calculatePrice")
|
||||||
|
//public Result<BigDecimal> calculatePrice(@RequestBody PriceCalculateVo priceCalculateVo) {
|
||||||
|
// return leaseProductMachineService.calculatePrice(priceCalculateVo);
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,173 @@
|
|||||||
|
package com.m2pool.lease.controller;
|
||||||
|
|
||||||
|
|
||||||
|
import com.m2pool.lease.dto.*;
|
||||||
|
import com.m2pool.lease.service.LeaseShopService;
|
||||||
|
import com.m2pool.lease.vo.BaseVo;
|
||||||
|
import com.m2pool.lease.vo.ShopConfigVo;
|
||||||
|
import com.m2pool.lease.vo.ShopVo;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 店铺表 前端控制器
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author yyb
|
||||||
|
* @since 2025-08-05
|
||||||
|
*/
|
||||||
|
@Api(tags = "店铺控制器")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/shop")
|
||||||
|
public class LeaseShopController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private LeaseShopService leaseShopService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增店铺
|
||||||
|
* @param shopVo 店铺信息
|
||||||
|
* @return 操作结果
|
||||||
|
*/
|
||||||
|
@ApiOperation("新增店铺")
|
||||||
|
@PostMapping("/addShop")
|
||||||
|
public Result<String> addShop(@RequestBody ShopVo shopVo) {
|
||||||
|
|
||||||
|
return leaseShopService.addShop(shopVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改店铺
|
||||||
|
* @param shopVo 店铺信息
|
||||||
|
* @return 操作结果
|
||||||
|
*/
|
||||||
|
@ApiOperation("根据店铺id修改店铺")
|
||||||
|
@PostMapping("/updateShop")
|
||||||
|
public Result<String> updateShop(@RequestBody ShopVo shopVo) {
|
||||||
|
return leaseShopService.updateShop(shopVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭/打开店铺
|
||||||
|
* @param baseVo 店铺 ID
|
||||||
|
* @return 操作结果
|
||||||
|
*/
|
||||||
|
@ApiOperation("根据店铺id关闭店铺")
|
||||||
|
@PostMapping("/closeShop")
|
||||||
|
public Result<String> closeShop(@RequestBody BaseVo baseVo) {
|
||||||
|
return leaseShopService.closeShop(baseVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据用户邮箱查询店铺
|
||||||
|
* @return 店铺信息
|
||||||
|
*/
|
||||||
|
@ApiOperation("根据用户邮箱查询店铺")
|
||||||
|
@GetMapping("/getShopByUserEmail")
|
||||||
|
public Result<ShopDto> getShopByUserEmail() {
|
||||||
|
return leaseShopService.getShopByUserEmail();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据店铺id查询店铺
|
||||||
|
* @param baseVo 店铺 ID
|
||||||
|
* @return 店铺信息
|
||||||
|
*/
|
||||||
|
@ApiOperation("根据店铺id查询店铺")
|
||||||
|
@PostMapping("/getShopById")
|
||||||
|
public Result<ShopDto> getShopById(@RequestBody BaseVo baseVo) {
|
||||||
|
return leaseShopService.getShopById(baseVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除店铺(逻辑删除)
|
||||||
|
* @param baseVo 店铺 ID
|
||||||
|
* @return 操作结果
|
||||||
|
*/
|
||||||
|
@ApiOperation("删除店铺")
|
||||||
|
@PostMapping("/deleteShop")
|
||||||
|
public Result<String> deleteShop(@RequestBody BaseVo baseVo) {
|
||||||
|
return leaseShopService.deleteShop(baseVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ApiOperation("根据店铺id获取到商品列表")
|
||||||
|
@PostMapping("/getProductListById")
|
||||||
|
public Result<List<ShopNameDto>> getProductListById(@RequestBody BaseVo baseVo) {
|
||||||
|
return leaseShopService.getProductListById(baseVo);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 根据店铺id 查询配置信息列表
|
||||||
|
* @param baseVo
|
||||||
|
* @return 操作结果
|
||||||
|
*/
|
||||||
|
@ApiOperation("钱包配置----根据店铺id查询收款钱包绑定信息列表")
|
||||||
|
@PostMapping("/getShopConfig")
|
||||||
|
public Result<List<ShopConfigDto>> getShopConfig(@RequestBody BaseVo baseVo) {
|
||||||
|
return leaseShopService.getShopConfig(baseVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增商铺配置 (新增配置时,如果没有指定商品,就默通用配置)
|
||||||
|
* @param shopConfigVo 商铺配置信息
|
||||||
|
* @return 操作结果
|
||||||
|
*/
|
||||||
|
@ApiOperation("钱包配置---新增商铺收款钱包绑定配置")
|
||||||
|
@PostMapping("/addShopConfig")
|
||||||
|
public Result<String> addShopConfig(@RequestBody ShopConfigVo shopConfigVo) {
|
||||||
|
return leaseShopService.addShopConfig(shopConfigVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改配置
|
||||||
|
* @param shopConfigVo 商铺配置信息
|
||||||
|
* @return 操作结果
|
||||||
|
*/
|
||||||
|
@ApiOperation("钱包配置----根据配置id 修改商铺收款钱包配置")
|
||||||
|
@PostMapping("/updateShopConfig")
|
||||||
|
public Result<String> updateShopConfig(@RequestBody ShopConfigVo shopConfigVo) {
|
||||||
|
return leaseShopService.updateShopConfig(shopConfigVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除配置(逻辑删除)
|
||||||
|
* @param baseVo 配置 ID
|
||||||
|
* @return 操作结果
|
||||||
|
*/
|
||||||
|
@ApiOperation("钱包配置----根据配置id 删除商铺收款钱包配置")
|
||||||
|
@PostMapping("/deleteShopConfig")
|
||||||
|
public Result<String> deleteShopConfig(@RequestBody BaseVo baseVo) {
|
||||||
|
return leaseShopService.deleteShopConfig(baseVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("钱包配置(用于充值选择链和币种)----获取链(一级)和币(二级) 下拉列表(获取本系统支持的链和币种)")
|
||||||
|
@PostMapping("/getChainAndList")
|
||||||
|
public Result<List<ChainListDto>> getChainAndList(){
|
||||||
|
return leaseShopService.getChainAndList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("钱包配置(用于下单选择商家支持的链和币种)----获取链(一级)和币(二级) 下拉列表(获取本商家支持的链和币种)")
|
||||||
|
@PostMapping("/getChainAndListForSeller")
|
||||||
|
public Result<List<ChainListDto>> getChainAndListForSeller(@RequestBody BaseVo baseVo){
|
||||||
|
return leaseShopService.getChainAndListForSeller(baseVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ApiOperation("钱包配置(用于修改卖家钱包地址)----获取链(一级)和币(二级) 下拉列表(获取本系统支持的链和币种)")
|
||||||
|
@PostMapping("/getChainAndCoin")
|
||||||
|
public Result<ChainListDto> getChainAndCoin(@RequestBody BaseVo baseVo){
|
||||||
|
return leaseShopService.getChainAndCoin(baseVo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
package com.m2pool.lease.controller;
|
||||||
|
|
||||||
|
|
||||||
|
import com.m2pool.lease.dto.PageResult;
|
||||||
|
import com.m2pool.lease.dto.Result;
|
||||||
|
import com.m2pool.lease.dto.ShopCartDto;
|
||||||
|
import com.m2pool.lease.service.LeaseShoppingCartService;
|
||||||
|
import com.m2pool.lease.vo.BaseVo;
|
||||||
|
import com.m2pool.lease.vo.PageVo;
|
||||||
|
import com.m2pool.lease.vo.ProductAndMachineVo;
|
||||||
|
import com.m2pool.lease.vo.ShoppingCartInfoURDVo;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 购物车表 前端控制器
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author yyb
|
||||||
|
* @since 2025-07-23
|
||||||
|
*/
|
||||||
|
@Api(tags = "购物车表控制器")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/shopping/cart")
|
||||||
|
public class LeaseShoppingCartController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private LeaseShoppingCartService leaseShoppingCartService;
|
||||||
|
|
||||||
|
@ApiOperation("添加商品到购物车(批量+单个)")
|
||||||
|
@PostMapping("/addGoods")
|
||||||
|
public Result<String> addGoods(@RequestBody List<ShoppingCartInfoURDVo> shoppingCartInfoURDVoList) {
|
||||||
|
return leaseShoppingCartService.addGoods(shoppingCartInfoURDVoList);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ApiOperation("查询购物车中商品列表")
|
||||||
|
@PostMapping("/getGoodsList")
|
||||||
|
public PageResult<ShopCartDto> getGoodsList(@RequestBody(required = false) PageVo pageVo) {
|
||||||
|
if (pageVo == null){
|
||||||
|
pageVo = new PageVo();
|
||||||
|
}
|
||||||
|
return leaseShoppingCartService.getGoodsList(pageVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("删除购物车中商品")
|
||||||
|
@PostMapping("/deleteGoods")
|
||||||
|
@Deprecated
|
||||||
|
public Result<String> deleteGoods(@RequestBody BaseVo baseVo) {
|
||||||
|
return leaseShoppingCartService.deleteGoods(baseVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("批量删除购物车中商品")
|
||||||
|
@PostMapping("/deleteBatchGoods")
|
||||||
|
public Result<String> deleteBatchGoods(@RequestBody List<ProductAndMachineVo> baseVoList) {
|
||||||
|
return leaseShoppingCartService.deleteBatchGoods(baseVoList);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("批量删除购物车中已下架商品")
|
||||||
|
@PostMapping("/deleteBatchGoodsForIsDelete")
|
||||||
|
public Result<String> deleteBatchGoodsForIsDelete() {
|
||||||
|
return leaseShoppingCartService.deleteBatchGoodsForIsDelete();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
package com.m2pool.lease.controller;
|
||||||
|
|
||||||
|
|
||||||
|
import com.m2pool.common.security.annotation.RequiresLogin;
|
||||||
|
import com.m2pool.lease.dto.*;
|
||||||
|
import com.m2pool.lease.service.LeaseUserService;
|
||||||
|
import com.m2pool.lease.vo.*;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 用户表 前端控制器
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author yyb
|
||||||
|
* @since 2025-07-23
|
||||||
|
*/
|
||||||
|
@Api(tags = "用户控制器")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/user")
|
||||||
|
public class LeaseUserController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private LeaseUserService leaseUserService;
|
||||||
|
@PostMapping("/login")
|
||||||
|
@ApiOperation(value = "用户登录/注册")
|
||||||
|
@Deprecated
|
||||||
|
public Result<UserDto> login(@RequestBody UserURDVo userURDVo){
|
||||||
|
return leaseUserService.login(userURDVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@PostMapping("/bindWallet")
|
||||||
|
@ApiOperation(value = "买家:充值步骤选择链和钱包后自动绑定钱包")
|
||||||
|
public Result<UserWalletDataDto> bindWallet(@RequestBody ChainAndCoinVo chainAndCoinVo){
|
||||||
|
return leaseUserService.bindWallet(chainAndCoinVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/getWalletInfo")
|
||||||
|
@ApiOperation(value = "获取用户相关钱包信息")
|
||||||
|
public Result<List<UserWalletDataDto>> getWalletInfo() {
|
||||||
|
return leaseUserService.getWalletInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@PostMapping("/withdrawBalance")
|
||||||
|
@ApiOperation(value = "申请余额提现")
|
||||||
|
public Result<String> withdrawBalance(@RequestBody BalanceVo balanceVo){
|
||||||
|
return leaseUserService.withdrawBalance(balanceVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@PostMapping("/balanceWithdrawList")
|
||||||
|
@ApiOperation(value = "买家:余额提现记录列表")
|
||||||
|
@Deprecated
|
||||||
|
public PageResult<PayWithdrawMessageDto> balanceWithdrawList(@RequestBody BalancePageVo balancePageVo){
|
||||||
|
return leaseUserService.balanceWithdrawList(balancePageVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@PostMapping("/balanceRechargeList")
|
||||||
|
@ApiOperation(value = "买家:余额充值记录列表")
|
||||||
|
@Deprecated
|
||||||
|
public PageResult<PayRechargeMessageDto> balanceRechargeList(@RequestBody BalancePageVo balancePageVo){
|
||||||
|
return leaseUserService.balanceRechargeList(balancePageVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/balancePayList")
|
||||||
|
@ApiOperation(value = "卖家:钱包交易(收款)记录列表")
|
||||||
|
public PageResult<PayRecordMessageDto> balancePayList(@RequestBody BalancePageVo balancePageVo){
|
||||||
|
return leaseUserService.balancePayList(balancePageVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/transactionRecord")
|
||||||
|
@ApiOperation(value = "买家:交易流水(支付,提现,充值)")
|
||||||
|
public PageResult<TransactionRecordDto> transactionRecord(@RequestBody RecordTypePageVo recordTypePageVo){
|
||||||
|
return leaseUserService.transactionRecord(recordTypePageVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/getRecentlyTransaction")
|
||||||
|
@ApiOperation(value = "最近5条交易")
|
||||||
|
public Result<List<RecentlyTransactionDto>> getRecentlyTransaction(){
|
||||||
|
return leaseUserService.getRecentlyTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@PostMapping("/getCharge")
|
||||||
|
@ApiOperation(value = "获取系统支持的交易手续费")
|
||||||
|
@Deprecated
|
||||||
|
public Result<List<ChargeDto>> getCharge(){
|
||||||
|
return leaseUserService.getCharge();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package com.m2pool.lease.dto;
|
||||||
|
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description 币种实时收益实体类
|
||||||
|
* @Date 2024/6/14 15:57
|
||||||
|
* @Author dy
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@ApiModel(description = "链(一级) 下拉列表返回对象",value = "ChainListDto")
|
||||||
|
public class ChainListDto {
|
||||||
|
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "链名value")
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "地址")
|
||||||
|
private String address;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "联名标签")
|
||||||
|
private String label;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "币(二级) 下拉列表")
|
||||||
|
private List<CoinListDto> children;
|
||||||
|
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@ApiModel(description = "币(二级) 下拉列表返回对象",value = "CoinListDto")
|
||||||
|
public static class CoinListDto{
|
||||||
|
@ApiModelProperty(value = "币种value")
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "币种label")
|
||||||
|
private String label;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "币种是否绑定(只用于卖家钱包绑定页面相关接口) 0 未绑定 1 已绑定")
|
||||||
|
private Integer hasBind;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package com.m2pool.lease.dto;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 余额提现请求对象
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author yyb
|
||||||
|
* @since 2025-07-23
|
||||||
|
*/
|
||||||
|
@Builder
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@ApiModel(description = "交易费接口",value = "ChargeDto")
|
||||||
|
public class ChargeDto {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "手续费",required = true)
|
||||||
|
private BigDecimal amount;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "链",required = true)
|
||||||
|
private String chain;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "币种",required = true)
|
||||||
|
private String coin;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package com.m2pool.lease.dto;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description 币种实时收益实体类
|
||||||
|
* @Date 2024/6/14 15:57
|
||||||
|
* @Author dy
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class CheckAddressDto {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 地址
|
||||||
|
*/
|
||||||
|
private String fromAddress;
|
||||||
|
|
||||||
|
private String fromChain;
|
||||||
|
|
||||||
|
private String fromSymbol;
|
||||||
|
/**
|
||||||
|
* 半年内是否有操作
|
||||||
|
*/
|
||||||
|
private String hasOperator;
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package com.m2pool.lease.dto;
|
||||||
|
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description 币种实时收益实体类
|
||||||
|
* @Date 2024/6/14 15:57
|
||||||
|
* @Author dy
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class CoinFullDto {
|
||||||
|
|
||||||
|
private String chainValue;
|
||||||
|
|
||||||
|
private String chainLabel;
|
||||||
|
|
||||||
|
|
||||||
|
private String coinValue;
|
||||||
|
|
||||||
|
private String coinLabel;
|
||||||
|
|
||||||
|
private Integer hasBind;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package com.m2pool.lease.dto;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 支付订单返回对象
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author yyb
|
||||||
|
* @since 2025-07-23
|
||||||
|
*/
|
||||||
|
@Builder
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@ApiModel(description = "已支付和理论支付总金额返回对象",value = "HasPayTotalDto")
|
||||||
|
public class HasPayTotalDto {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 理论支付金额
|
||||||
|
*/
|
||||||
|
private BigDecimal totalAmount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 实际支付金额
|
||||||
|
*/
|
||||||
|
private BigDecimal totalRealAmount;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package com.m2pool.lease.dto;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description 币种实时收益实体类
|
||||||
|
* @Date 2024/6/14 15:57
|
||||||
|
* @Author dy
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class HourIncomeDto{
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 挖矿账户
|
||||||
|
*/
|
||||||
|
private String user;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 矿工编号
|
||||||
|
*/
|
||||||
|
private String miner;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 挖矿收益nexa 币
|
||||||
|
*/
|
||||||
|
private BigDecimal income;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 挖矿收益 稳定币usdt
|
||||||
|
*/
|
||||||
|
private BigDecimal usdtIncome;
|
||||||
|
|
||||||
|
private LocalDateTime createTime;
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package com.m2pool.lease.dto;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 已售商品矿工实时算力表
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author yyb
|
||||||
|
* @since 2025-07-25
|
||||||
|
*/
|
||||||
|
@Builder
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class MachinePowerDto{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ID
|
||||||
|
*/
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 挖矿账户
|
||||||
|
*/
|
||||||
|
private String user;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 矿工
|
||||||
|
*/
|
||||||
|
private String miner;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记录时间(每五分钟整点)
|
||||||
|
*/
|
||||||
|
private LocalDateTime date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 五分钟一次的矿工矿机算力
|
||||||
|
*/
|
||||||
|
private BigDecimal accepts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 矿机在离线状态 离线offline 在线online
|
||||||
|
*/
|
||||||
|
private String state;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 实际记录时间
|
||||||
|
*/
|
||||||
|
private LocalDateTime lastSubmit;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
package com.m2pool.lease.dto;
|
||||||
|
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 订单详情返回对象
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author yyb
|
||||||
|
* @since 2025-07-23
|
||||||
|
*/
|
||||||
|
@Builder
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@ApiModel(description = "订单详情返回对象",value = "OrderInfoDto")
|
||||||
|
public class OrderInfoDto {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单 ID
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "订单 ID")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "店铺id")
|
||||||
|
private Long shopId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单号
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "订单号")
|
||||||
|
private String orderNumber;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户id
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "用户id")
|
||||||
|
private String userId;
|
||||||
|
/**
|
||||||
|
* 订单总价
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "订单总价")
|
||||||
|
private BigDecimal totalPrice;
|
||||||
|
|
||||||
|
///**
|
||||||
|
// * 收货地址
|
||||||
|
// */
|
||||||
|
//private String address;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单状态 0待付款 1待发货 2待收货 3待评价 4已完成 5取消订单
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "订单状态 7 订单进行中 8 订单已完成")
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "创建时间")
|
||||||
|
private LocalDateTime createTime;
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------- 一个普通订单对应一个支付订单(多个封装下面四个字段为一个对象,并返回list)----------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "二维码图片")
|
||||||
|
private String img;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "需支付总金额")
|
||||||
|
private BigDecimal amount;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "已支付金额")
|
||||||
|
private String payAmount;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "未支付金额")
|
||||||
|
private Double noPayAmount;
|
||||||
|
|
||||||
|
//---------------------------------------------- 一个普通订单对应一个支付订单(多个封装下面四个字段为一个对象,并返回list)- ----------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
* 订单详情
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "订单详情")
|
||||||
|
private List<OrderItemDto> orderItemDtoList;
|
||||||
|
}
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
package com.m2pool.lease.dto;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 订单列表返回对象
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author yyb
|
||||||
|
* @since 2025-07-23
|
||||||
|
*/
|
||||||
|
@Builder
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@ApiModel(description = "订单列表返回对象",value = "LeaseOrderItemDto")
|
||||||
|
public class OrderItemDto {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单 ID
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "订单 ID")
|
||||||
|
private Long orderId;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "店铺id")
|
||||||
|
private Long shopId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品 ID
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "商品 ID")
|
||||||
|
private Long productId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 机器id
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "机器id")
|
||||||
|
private Long productMachineId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品租期天数
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "商品租期天数")
|
||||||
|
private Integer leaseTime;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品名称
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "商品名称")
|
||||||
|
private String name;
|
||||||
|
/**
|
||||||
|
* 商品图片路径
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "商品图片路径")
|
||||||
|
private String image;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 收货地址(模拟)
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "收货地址(模拟)")
|
||||||
|
private String address;
|
||||||
|
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "机器单价")
|
||||||
|
private BigDecimal price;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付币种
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "支付币种")
|
||||||
|
private String payCoin;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package com.m2pool.lease.dto;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 订单状态修改返回对象
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author yyb
|
||||||
|
* @since 2025-07-23
|
||||||
|
*/
|
||||||
|
@Builder
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@ApiModel(description = "订单状态修改返回对象",value = "OrderStatusDto")
|
||||||
|
public class OrderStatusDto {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单 ID
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "订单 ID")
|
||||||
|
private Long orderId;
|
||||||
|
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "订单主表状态")
|
||||||
|
private Integer orderInfoStatus;
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package com.m2pool.lease.dto;
|
||||||
|
|
||||||
|
import com.github.pagehelper.PageInfo;
|
||||||
|
import com.m2pool.lease.constant.ResponseConstant;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description 表格分页数据对象
|
||||||
|
* @Date 2024/6/13 11:59
|
||||||
|
* @Author dy
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@ApiModel(description = "分页返回对象")
|
||||||
|
public class PageResult<T> implements Serializable
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
|
||||||
|
/** 成功 */
|
||||||
|
public static final int SUCCESS = ResponseConstant.SUCCESS;
|
||||||
|
|
||||||
|
/** 失败 */
|
||||||
|
public static final int FAIL = ResponseConstant.FAIL;
|
||||||
|
|
||||||
|
/** 总记录数 */
|
||||||
|
@ApiModelProperty(value = "总记录数", example = "1")
|
||||||
|
private long total;
|
||||||
|
|
||||||
|
/** 总页数 */
|
||||||
|
@ApiModelProperty(value = "总页数", example = "1")
|
||||||
|
private long totalPage;
|
||||||
|
|
||||||
|
/** 列表数据 */
|
||||||
|
@ApiModelProperty(value = "查询结果集合")
|
||||||
|
private List<T> rows;
|
||||||
|
|
||||||
|
/** 消息状态码 */
|
||||||
|
@ApiModelProperty(value = "消息状态码", example = "200")
|
||||||
|
private int code;
|
||||||
|
|
||||||
|
/** 消息内容 */
|
||||||
|
@ApiModelProperty(value = "查询结果描述", example = "成功")
|
||||||
|
private String msg;
|
||||||
|
|
||||||
|
public static <T> PageResult<T> success(List<T> data)
|
||||||
|
{
|
||||||
|
return setPageResult(data, SUCCESS, "成功");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> PageResult<T> fail(List<T> data, String msg)
|
||||||
|
{
|
||||||
|
return setPageResult(data, FAIL, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> PageResult<T> setPageResult(List<T> data, int code, String msg)
|
||||||
|
{
|
||||||
|
PageResult<T> rspData = new PageResult<T>();
|
||||||
|
rspData.setCode(SUCCESS);
|
||||||
|
rspData.setRows(data);
|
||||||
|
rspData.setMsg("查询成功");
|
||||||
|
return rspData;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package com.m2pool.lease.dto;
|
||||||
|
|
||||||
|
import com.m2pool.lease.vo.BaseVo;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 店铺商品配置返回对象
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author yyb
|
||||||
|
* @since 2025-08-05
|
||||||
|
*/
|
||||||
|
@Builder
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@ApiModel(description = "商品收款钱包配置",value = "PayConfigDto")
|
||||||
|
public class PayConfigDto {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nexa rxd dgbo dgbq dgbs alph enx grs mona usdt
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "支持的支付币种")
|
||||||
|
private String payCoin;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 卖方对应收款钱包
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "币种图标")
|
||||||
|
private String payCoinImage;
|
||||||
|
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "链")
|
||||||
|
private String payChain;
|
||||||
|
|
||||||
|
|
||||||
|
private Long shopId;
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package com.m2pool.lease.dto;
|
||||||
|
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 支付订单返回对象
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author yyb
|
||||||
|
* @since 2025-07-23
|
||||||
|
*/
|
||||||
|
@Builder
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@ApiModel(description = "支付订单返回对象",value = "PayOrderDto")
|
||||||
|
public class PayOrderDto {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付方式,nexa rxd dgbo dgbq dgbs alph enx grs mona usdt usdc busd
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "支付方式,nexa rxd dgbo dgbq dgbs alph enx grs mona usdt usdc busd")
|
||||||
|
private String payCoin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付金额
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "支付金额")
|
||||||
|
private BigDecimal amount;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付地址
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "支付地址")
|
||||||
|
private String payAddress;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
package com.m2pool.lease.dto;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 充值记录表
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author yyb
|
||||||
|
* @since 2025-09-10
|
||||||
|
*/
|
||||||
|
@Builder
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@ApiModel(description = "余额充值返回对象",value = "PayRechargeMessageDto" )
|
||||||
|
public class PayRechargeMessageDto {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 充值地址
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "充值地址(官方自动生成绑定地址)")
|
||||||
|
private String address;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付金额
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "充值金额")
|
||||||
|
private BigDecimal amount;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 币种
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "币种")
|
||||||
|
private String fromSymbol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 链名称
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "链名称")
|
||||||
|
private String fromChain;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 充值时间
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "充值到账时间)")
|
||||||
|
private LocalDateTime createTime;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 0 充值失败 1 充值成功 2 充值中
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "充值状态 0 充值失败 1 充值成功 2 充值中 3 校验失败")
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 交易hash
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "交易hash")
|
||||||
|
private String txHash;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
package com.m2pool.lease.dto;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 支付消息记录表
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author yyb
|
||||||
|
* @since 2025-09-10
|
||||||
|
*/
|
||||||
|
@Builder
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@ApiModel(description = "支付返回对象",value = "PayRecordMessageDto" )
|
||||||
|
public class PayRecordMessageDto {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息ID
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "消息ID")
|
||||||
|
private String queueId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 买家充值地址
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "买家钱包地址")
|
||||||
|
private String fromAddress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 卖家地址(卖家自定义地址)
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "收款地址(卖家自定义地址)")
|
||||||
|
private String toAddress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付金额
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "理论支付支付金额")
|
||||||
|
private BigDecimal amount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*实际支付金额(根据一天内预估算力和实际算力差值计算得来,并且已经真实支付成功的金额)
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "实际支付金额(根据一天内预估算力和实际算力差值计算得来,并且已经真实支付成功的金额)")
|
||||||
|
private BigDecimal realAmount;
|
||||||
|
/**
|
||||||
|
* 卖家钱包币种
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "收款钱包币种")
|
||||||
|
private String toSymbol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 卖家钱包链名称
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "收款钱包链名称")
|
||||||
|
private String toChain;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 买家钱包币种
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "买家钱包币种")
|
||||||
|
private String fromSymbol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 买家钱包链名称
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "买家钱包链名称")
|
||||||
|
private String fromChain;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 交易hash
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "交易hash")
|
||||||
|
private String txHash;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单号
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "订单号")
|
||||||
|
private String orderId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付时间
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "支付时间")
|
||||||
|
private LocalDateTime createTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新时间
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "支付成功/失败/证书校验失败时间")
|
||||||
|
private LocalDateTime updateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 0 支付失败 1 支付成功 2 等待校验 3 证书校验失败
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "支付状态 0 支付失败 1 支付成功 2 待校验 3 校验失败")
|
||||||
|
private Integer status;
|
||||||
|
}
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
package com.m2pool.lease.dto;
|
||||||
|
|
||||||
|
import com.alibaba.nacos.shaded.org.checkerframework.checker.units.qual.A;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 余额提现返回对象
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author yyb
|
||||||
|
* @since 2025-09-10
|
||||||
|
*/
|
||||||
|
@Builder
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@ApiModel(description = "余额提现返回对象",value = "PayWithdrawMessageDto" )
|
||||||
|
public class PayWithdrawMessageDto {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户充值地址
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "用户充值地址")
|
||||||
|
private String fromAddress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提现地址(用户自定义)
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "提现地址(用户自定义)")
|
||||||
|
private String toAddress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付金额
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "提现金额")
|
||||||
|
private BigDecimal amount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 币种
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "币种")
|
||||||
|
private String toSymbol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 链名称
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "链名称")
|
||||||
|
private String toChain;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 币种
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "币种")
|
||||||
|
private String fromSymbol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 链名称
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "链名称")
|
||||||
|
private String fromChain;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 充值时间
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "提现时间")
|
||||||
|
private LocalDateTime createTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新时间
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "提现完成时间")
|
||||||
|
private LocalDateTime updateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 0 支付失败 1 支付成功 2 支付中
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "记录状态 提现业务: 0 提现失败 1 提现成功 2 提现中 3 校验失败")
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 交易hash
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "交易hash")
|
||||||
|
private String txHash;
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package com.m2pool.lease.dto;
|
||||||
|
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 支付回调结果返回对象
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author yyb
|
||||||
|
* @since 2025-07-23
|
||||||
|
*/
|
||||||
|
@Builder
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@ApiModel(description = "支付回调结果返回对象",value = "PaymentCallbackDto")
|
||||||
|
public class PaymentCallbackDto {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "本次支付是否支付完成 ---- 支付状态0支付失败 1支付成功--全部货款已支付 2待支付 5支付已超时 10支付成功--已支付部分货款 ")
|
||||||
|
private int isPayAll;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "剩余未支付的金额")
|
||||||
|
private BigDecimal noPayAmount;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "需要支付的总金额 = payAmount + noPayAmount")
|
||||||
|
private BigDecimal totalAmount;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "已支付的金额(从卖方钱包交易记录中获取的)")
|
||||||
|
private BigDecimal payAmount;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "卖方二维码图片(如果支付状态为 1 则不再返回该字段)")
|
||||||
|
private String img;
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user