BUG修复:支付、时长、套餐
This commit is contained in:
parent
bd428814a3
commit
d8b9992b23
|
@ -2,7 +2,7 @@ package com.ruoyi.common.constant;
|
|||
|
||||
/**
|
||||
* 缓存的key 常量
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class CacheConstants
|
||||
|
@ -41,4 +41,8 @@ public class CacheConstants
|
|||
* 登录账户密码错误次数 redis key
|
||||
*/
|
||||
public static final String PWD_ERR_CNT_KEY = "pwd_err_cnt:";
|
||||
|
||||
public static final String ACCESS_KEY_PREFIX = "access:";
|
||||
|
||||
public static final String USER_PREFIX = "user:";
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import java.util.concurrent.TimeUnit;
|
|||
|
||||
/**
|
||||
* 通用常量信息
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class Constants
|
||||
|
@ -193,4 +193,13 @@ public class Constants
|
|||
public static final TimeUnit BILL_UNPAID_TIMEUNIT = TimeUnit.MINUTES;
|
||||
|
||||
|
||||
/**
|
||||
* accessKey
|
||||
*/
|
||||
public static final String HEADER_ACCESS_KEY = "accessKey";
|
||||
|
||||
/**
|
||||
* accessSecret
|
||||
*/
|
||||
public static final String HEADER_ACCESS_SECRET = "accessSecret";
|
||||
}
|
||||
|
|
|
@ -33,11 +33,11 @@ public class RedisLock {
|
|||
private Integer retry;
|
||||
|
||||
|
||||
public boolean unlock(RedisLockKey redisLockKey, String key) {
|
||||
public boolean unlock(RedisLockKey redisLockKey, Object key) {
|
||||
return unlock(redisLockKey.getKey() + ":" + key);
|
||||
}
|
||||
|
||||
public boolean lock(RedisLockKey redisLockKey, String key) {
|
||||
public boolean lock(RedisLockKey redisLockKey, Object key) {
|
||||
return lock(redisLockKey.getKey() + ":" + key);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,9 @@ public enum RedisLockKey {
|
|||
ADD_WITHDRAW("addWithdraw", "提现申请"),
|
||||
APPROVAL_WITHDRAW("approvalWithdraw", "提现审核"),
|
||||
PAY_WITHDRAW("payWithdraw", "提现打款"),
|
||||
PAY_NOTIFY("payNotify", "支付通知");
|
||||
PAY_NOTIFY("payNotify", "支付通知"),
|
||||
APPLY_ACCESS("apply_access", "申请秘钥"),
|
||||
RECHARGE_DEVICE("recharge_device", "设备充值");
|
||||
|
||||
|
||||
private final String key;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.ruoyi.common.utils;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Base64;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -197,4 +199,14 @@ public class SecurityUtils
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 安全的生成秘钥
|
||||
* @param length 秘钥长度
|
||||
*/
|
||||
public static String genSecret(int length) {
|
||||
SecureRandom secureRandom = new SecureRandom();
|
||||
byte[] accessSecretBytes = new byte[length];
|
||||
secureRandom.nextBytes(accessSecretBytes);
|
||||
return Base64.getEncoder().encodeToString(accessSecretBytes);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package com.ruoyi.framework.security.domain;
|
||||
|
||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||
import com.ruoyi.ss.access.domain.AccessVO;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author wjh
|
||||
* 2024/7/18
|
||||
*/
|
||||
@Data
|
||||
public class AccessLoginUser {
|
||||
|
||||
// 秘钥
|
||||
private AccessVO access;
|
||||
|
||||
// 登录用户信息
|
||||
private LoginUser loginUser;
|
||||
}
|
|
@ -1,10 +1,20 @@
|
|||
package com.ruoyi.framework.security.filter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.ruoyi.common.constant.CacheConstants;
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
import com.ruoyi.common.core.redis.RedisCache;
|
||||
import com.ruoyi.framework.security.domain.AccessLoginUser;
|
||||
import com.ruoyi.ss.access.domain.AccessVO;
|
||||
import com.ruoyi.ss.access.service.AccessService;
|
||||
import com.ruoyi.ss.user.domain.SmUserVo;
|
||||
import com.ruoyi.ss.user.service.ISmUserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
@ -18,7 +28,7 @@ import com.ruoyi.framework.web.service.TokenService;
|
|||
|
||||
/**
|
||||
* token过滤器 验证token有效性
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Component
|
||||
|
@ -27,18 +37,79 @@ public class JwtAuthenticationTokenFilter extends OncePerRequestFilter
|
|||
@Autowired
|
||||
private TokenService tokenService;
|
||||
|
||||
@Autowired
|
||||
private AccessService accessService;
|
||||
|
||||
@Autowired
|
||||
private ISmUserService userService;
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
|
||||
throws ServletException, IOException
|
||||
{
|
||||
LoginUser loginUser = tokenService.getLoginUser(request);
|
||||
if (StringUtils.isNotNull(loginUser) && StringUtils.isNull(SecurityUtils.getAuthentication()))
|
||||
{
|
||||
tokenService.verifyToken(loginUser);
|
||||
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
|
||||
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
||||
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
|
||||
// 判断上下文是否已经存在用户信息
|
||||
if (StringUtils.isNull(SecurityUtils.getAuthentication())) {
|
||||
// 优先尝试使用token来获取用户信息
|
||||
LoginUser loginUser = tokenService.getLoginUser(request);
|
||||
if (loginUser != null) {
|
||||
tokenService.verifyToken(loginUser);
|
||||
}
|
||||
// 若token未获取到信息,则使用accessKey来获取用户信息
|
||||
else {
|
||||
loginUser = this.getLoginUserByAccessKey(request);
|
||||
}
|
||||
|
||||
// 最后判断用户是否为空,并将其写入到安全上下文
|
||||
if (loginUser != null) {
|
||||
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
|
||||
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
||||
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
|
||||
}
|
||||
}
|
||||
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
|
||||
private LoginUser getLoginUserByAccessKey(HttpServletRequest request) {
|
||||
String accessKey = request.getHeader(Constants.HEADER_ACCESS_KEY);
|
||||
String accessSecret = request.getHeader(Constants.HEADER_ACCESS_SECRET);
|
||||
if (StringUtils.isBlank(accessKey) || StringUtils.isBlank(accessSecret)) {
|
||||
return null;
|
||||
}
|
||||
// 从缓存中获取数据
|
||||
String redisKey = CacheConstants.ACCESS_KEY_PREFIX + accessKey;
|
||||
AccessLoginUser accessLoginUser = redisCache.getCacheObject(redisKey);
|
||||
|
||||
// 缓存未命中,查询获取数据
|
||||
if (accessLoginUser == null) {
|
||||
accessLoginUser = new AccessLoginUser();
|
||||
|
||||
// 获取access信息
|
||||
AccessVO access = accessService.selectByAccessKey(accessKey);
|
||||
if (access == null) {
|
||||
return null;
|
||||
}
|
||||
accessLoginUser.setAccess(access);
|
||||
|
||||
// 获取用户信息
|
||||
SmUserVo user = userService.selectSmUserByUserId(accessLoginUser.getAccess().getUserId());
|
||||
if (user == null) {
|
||||
return null;
|
||||
}
|
||||
LoginUser loginUser = new LoginUser(user.getUserId(), user);
|
||||
accessLoginUser.setLoginUser(loginUser);
|
||||
|
||||
// 放入缓存中
|
||||
redisCache.setCacheObject(redisKey, accessLoginUser, 30, TimeUnit.MINUTES);
|
||||
}
|
||||
|
||||
// 校验秘钥
|
||||
if (!SecurityUtils.matchesPassword(accessSecret, accessLoginUser.getAccess().getAccessSecret())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return accessLoginUser.getLoginUser();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
package com.ruoyi.ss.access.domain;
|
||||
|
||||
import com.ruoyi.common.annotation.Sensitive;
|
||||
import com.ruoyi.common.enums.DesensitizedType;
|
||||
import lombok.Data;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
|
||||
/**
|
||||
* 第三方API秘钥对对象 ss_access
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2024-07-17
|
||||
*/
|
||||
@Data
|
||||
public class Access extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 秘钥对ID */
|
||||
private Long accessId;
|
||||
|
||||
/** 申请用户ID */
|
||||
@Excel(name = "申请用户ID")
|
||||
private Long userId;
|
||||
|
||||
/** 秘钥键 */
|
||||
@Excel(name = "秘钥键")
|
||||
private String accessKey;
|
||||
|
||||
/** 秘钥(加密) */
|
||||
@Excel(name = "秘钥")
|
||||
@Sensitive(desensitizedType = DesensitizedType.PASSWORD)
|
||||
private String accessSecret;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package com.ruoyi.ss.access.domain;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author wjh
|
||||
* 2024/7/17
|
||||
*/
|
||||
@Data
|
||||
public class AccessQuery extends Access{
|
||||
|
||||
@ApiModelProperty("密钥对id列表")
|
||||
private List<Long> accessIds;
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package com.ruoyi.ss.access.domain;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author wjh
|
||||
* 2024/7/17
|
||||
*/
|
||||
@Data
|
||||
public class AccessVO extends Access{
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.ruoyi.ss.access.domain.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author wjh
|
||||
* 2024/7/17
|
||||
*/
|
||||
@Data
|
||||
public class AccessLoginDTO {
|
||||
|
||||
@ApiModelProperty("秘钥键")
|
||||
private String accessKey;
|
||||
|
||||
@ApiModelProperty("秘钥")
|
||||
private String accessSecret;
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package com.ruoyi.ss.access.domain.vo;
|
||||
|
||||
import com.ruoyi.ss.access.domain.Access;
|
||||
import com.ruoyi.ss.access.domain.AccessVO;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 申请的密钥对返回值
|
||||
* @author wjh
|
||||
* 2024/7/17
|
||||
*/
|
||||
@Data
|
||||
public class AccessApplyVO {
|
||||
|
||||
@ApiModelProperty("秘钥键")
|
||||
private String accessKey;
|
||||
|
||||
@ApiModelProperty("秘钥")
|
||||
private String accessSecret;
|
||||
|
||||
public AccessApplyVO(Access access) {
|
||||
this.accessKey = access.getAccessKey();
|
||||
this.accessSecret = access.getAccessSecret();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
package com.ruoyi.ss.access.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import com.ruoyi.ss.access.domain.Access;
|
||||
import com.ruoyi.ss.access.domain.AccessQuery;
|
||||
import com.ruoyi.ss.access.domain.AccessVO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
/**
|
||||
* 第三方API秘钥对Mapper接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2024-07-17
|
||||
*/
|
||||
public interface AccessMapper
|
||||
{
|
||||
/**
|
||||
* 查询第三方API秘钥对
|
||||
*
|
||||
* @param accessId 第三方API秘钥对主键
|
||||
* @return 第三方API秘钥对
|
||||
*/
|
||||
public AccessVO selectAccessByAccessId(Long accessId);
|
||||
|
||||
/**
|
||||
* 查询第三方API秘钥对列表
|
||||
*
|
||||
* @param access 第三方API秘钥对
|
||||
* @return 第三方API秘钥对集合
|
||||
*/
|
||||
public List<AccessVO> selectAccessList(AccessQuery access);
|
||||
|
||||
/**
|
||||
* 新增第三方API秘钥对
|
||||
*
|
||||
* @param access 第三方API秘钥对
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertAccess(Access access);
|
||||
|
||||
/**
|
||||
* 修改第三方API秘钥对
|
||||
*
|
||||
* @param access 第三方API秘钥对
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateAccess(Access access);
|
||||
|
||||
/**
|
||||
* 删除第三方API秘钥对
|
||||
*
|
||||
* @param accessId 第三方API秘钥对主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteAccessByAccessId(Long accessId);
|
||||
|
||||
/**
|
||||
* 批量删除第三方API秘钥对
|
||||
*
|
||||
* @param accessIds 需要删除的数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteAccessByAccessIds(@Param("ids") List<Long> accessIds);
|
||||
|
||||
/**
|
||||
* 根据用户ID查询数量
|
||||
*/
|
||||
int selectCountByUserId(Long userId);
|
||||
|
||||
/**
|
||||
* 根据accessKey查询密钥对
|
||||
*/
|
||||
AccessVO selectByAccessKey(String accessKey);
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.ruoyi.ss.access.mapper.AccessMapper">
|
||||
|
||||
<resultMap type="AccessVO" id="AccessResult" autoMapping="true"/>
|
||||
|
||||
<sql id="selectAccessVo">
|
||||
select
|
||||
sa.access_id,
|
||||
sa.user_id,
|
||||
sa.access_key,
|
||||
sa.access_secret,
|
||||
sa.create_time
|
||||
from ss_access sa
|
||||
</sql>
|
||||
|
||||
<select id="selectAccessList" parameterType="AccessQuery" resultMap="AccessResult">
|
||||
<include refid="selectAccessVo"/>
|
||||
<where>
|
||||
<if test="accessId != null "> and sa.access_id = #{accessId}</if>
|
||||
<if test="userId != null "> and sa.user_id = #{userId}</if>
|
||||
<if test="accessKey != null and accessKey != ''"> and sa.access_key = #{accessKey}</if>
|
||||
<if test="accessSecret != null and accessSecret != ''"> and sa.access_secret = #{accessSecret}</if>
|
||||
<if test="accessIds != null and accessIds.size() > 0">
|
||||
and sa.access_id in
|
||||
<foreach collection="accessIds" item="accessId" open="(" separator="," close=")">
|
||||
#{accessId}
|
||||
</foreach>
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<select id="selectAccessByAccessId" parameterType="Long" resultMap="AccessResult">
|
||||
<include refid="selectAccessVo"/>
|
||||
where sa.access_id = #{accessId}
|
||||
</select>
|
||||
|
||||
<select id="selectCountByUserId" resultType="java.lang.Integer">
|
||||
select count(sa.access_id)
|
||||
from ss_access sa
|
||||
where sa.user_id = #{userId}
|
||||
</select>
|
||||
|
||||
<select id="selectByAccessKey" resultType="com.ruoyi.ss.access.domain.AccessVO">
|
||||
<include refid="selectAccessVo"/>
|
||||
where sa.access_key = #{accessKey}
|
||||
</select>
|
||||
|
||||
<insert id="insertAccess" parameterType="Access" useGeneratedKeys="true" keyProperty="accessId">
|
||||
insert into ss_access
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="userId != null">user_id,</if>
|
||||
<if test="accessKey != null and accessKey != ''">access_key,</if>
|
||||
<if test="accessSecret != null and accessSecret != ''">access_secret,</if>
|
||||
<if test="createTime != null">create_time,</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="userId != null">#{userId},</if>
|
||||
<if test="accessKey != null and accessKey != ''">#{accessKey},</if>
|
||||
<if test="accessSecret != null and accessSecret != ''">#{accessSecret},</if>
|
||||
<if test="createTime != null">#{createTime},</if>
|
||||
</trim>
|
||||
</insert>
|
||||
|
||||
<update id="updateAccess" parameterType="Access">
|
||||
update ss_access
|
||||
<trim prefix="SET" suffixOverrides=",">
|
||||
<if test="userId != null">user_id = #{userId},</if>
|
||||
<if test="accessKey != null and accessKey != ''">access_key = #{accessKey},</if>
|
||||
<if test="accessSecret != null and accessSecret != ''">access_secret = #{accessSecret},</if>
|
||||
<if test="createTime != null">create_time = #{createTime},</if>
|
||||
</trim>
|
||||
where access_id = #{accessId}
|
||||
</update>
|
||||
|
||||
<delete id="deleteAccessByAccessId" parameterType="Long">
|
||||
delete from ss_access where access_id = #{accessId}
|
||||
</delete>
|
||||
|
||||
<delete id="deleteAccessByAccessIds" parameterType="String">
|
||||
delete from ss_access where access_id in
|
||||
<foreach item="accessId" collection="ids" open="(" separator="," close=")">
|
||||
#{accessId}
|
||||
</foreach>
|
||||
</delete>
|
||||
</mapper>
|
|
@ -0,0 +1,92 @@
|
|||
package com.ruoyi.ss.access.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.ruoyi.ss.access.domain.Access;
|
||||
import com.ruoyi.ss.access.domain.AccessQuery;
|
||||
import com.ruoyi.ss.access.domain.AccessVO;
|
||||
import com.ruoyi.ss.access.domain.vo.AccessApplyVO;
|
||||
import com.ruoyi.ss.user.domain.SmUserVo;
|
||||
|
||||
/**
|
||||
* 第三方API秘钥对Service接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2024-07-17
|
||||
*/
|
||||
public interface AccessService
|
||||
{
|
||||
/**
|
||||
* 查询第三方API秘钥对
|
||||
*
|
||||
* @param accessId 第三方API秘钥对主键
|
||||
* @return 第三方API秘钥对
|
||||
*/
|
||||
public AccessVO selectAccessByAccessId(Long accessId);
|
||||
|
||||
/**
|
||||
* 查询第三方API秘钥对列表
|
||||
*
|
||||
* @param access 第三方API秘钥对
|
||||
* @return 第三方API秘钥对集合
|
||||
*/
|
||||
public List<AccessVO> selectAccessList(AccessQuery access);
|
||||
|
||||
/**
|
||||
* 新增第三方API秘钥对
|
||||
*
|
||||
* @param access 第三方API秘钥对
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertAccess(Access access);
|
||||
|
||||
/**
|
||||
* 修改第三方API秘钥对
|
||||
*
|
||||
* @param access 第三方API秘钥对
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateAccess(Access access);
|
||||
|
||||
/**
|
||||
* 批量删除第三方API秘钥对
|
||||
*
|
||||
* @param accessIds 需要删除的第三方API秘钥对主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteAccessByAccessIds(List<Long> accessIds);
|
||||
|
||||
/**
|
||||
* 删除第三方API秘钥对信息
|
||||
*
|
||||
* @param accessId 第三方API秘钥对主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteAccessByAccessId(Long accessId);
|
||||
|
||||
/**
|
||||
* 用户申请新的秘钥对
|
||||
*
|
||||
* @param userId 用户ID
|
||||
*/
|
||||
AccessApplyVO apply(Long userId);
|
||||
|
||||
/**
|
||||
* 查询用户秘钥对数量
|
||||
*/
|
||||
int selectCountByUserId(Long userId);
|
||||
|
||||
SmUserVo selectUserByAccess(String accessKey);
|
||||
|
||||
/**
|
||||
* 根据accessKey查询秘钥对
|
||||
*/
|
||||
AccessVO selectByAccessKey(String accessKey);
|
||||
|
||||
/**
|
||||
* 删除缓存
|
||||
*/
|
||||
boolean deleteCache(String accessKey);
|
||||
|
||||
AccessApplyVO reset(Long accessId);
|
||||
}
|
|
@ -0,0 +1,214 @@
|
|||
package com.ruoyi.ss.access.service.impl;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.ruoyi.common.constant.CacheConstants;
|
||||
import com.ruoyi.common.core.redis.RedisCache;
|
||||
import com.ruoyi.common.core.redis.RedisLock;
|
||||
import com.ruoyi.common.core.redis.enums.RedisLockKey;
|
||||
import com.ruoyi.common.utils.*;
|
||||
import com.ruoyi.common.utils.collection.CollectionUtils;
|
||||
import com.ruoyi.ss.access.domain.AccessQuery;
|
||||
import com.ruoyi.ss.access.domain.AccessVO;
|
||||
import com.ruoyi.ss.access.domain.vo.AccessApplyVO;
|
||||
import com.ruoyi.ss.user.domain.SmUserVo;
|
||||
import com.ruoyi.ss.user.service.ISmUserService;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.ruoyi.ss.access.mapper.AccessMapper;
|
||||
import com.ruoyi.ss.access.domain.Access;
|
||||
import com.ruoyi.ss.access.service.AccessService;
|
||||
|
||||
/**
|
||||
* 第三方API秘钥对Service业务层处理
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2024-07-17
|
||||
*/
|
||||
@Service
|
||||
public class AccessServiceImpl implements AccessService
|
||||
{
|
||||
@Autowired
|
||||
private AccessMapper accessMapper;
|
||||
|
||||
@Value("${access.maxCount}")
|
||||
private Integer maxCount;
|
||||
|
||||
@Autowired
|
||||
private RedisLock redisLock;
|
||||
|
||||
@Autowired
|
||||
private ISmUserService userService;
|
||||
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
|
||||
/**
|
||||
* 查询第三方API秘钥对
|
||||
*
|
||||
* @param accessId 第三方API秘钥对主键
|
||||
* @return 第三方API秘钥对
|
||||
*/
|
||||
@Override
|
||||
public AccessVO selectAccessByAccessId(Long accessId)
|
||||
{
|
||||
return accessMapper.selectAccessByAccessId(accessId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询第三方API秘钥对列表
|
||||
*
|
||||
* @param access 第三方API秘钥对
|
||||
* @return 第三方API秘钥对
|
||||
*/
|
||||
@Override
|
||||
public List<AccessVO> selectAccessList(AccessQuery access)
|
||||
{
|
||||
return accessMapper.selectAccessList(access);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增第三方API秘钥对
|
||||
*
|
||||
* @param access 第三方API秘钥对
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int insertAccess(Access access)
|
||||
{
|
||||
access.setCreateTime(DateUtils.getNowDate());
|
||||
return accessMapper.insertAccess(access);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改第三方API秘钥对
|
||||
*
|
||||
* @param data 第三方API秘钥对
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int updateAccess(Access data)
|
||||
{
|
||||
int update = accessMapper.updateAccess(data);
|
||||
if (update == 1) {
|
||||
// 刷新缓存
|
||||
AccessVO access = selectAccessByAccessId(data.getAccessId());
|
||||
this.deleteCache(access.getAccessKey());
|
||||
}
|
||||
return update;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除第三方API秘钥对
|
||||
*
|
||||
* @param accessIds 需要删除的第三方API秘钥对主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteAccessByAccessIds(List<Long> accessIds)
|
||||
{
|
||||
if (CollectionUtils.isEmptyElement(accessIds)) {
|
||||
return 0;
|
||||
}
|
||||
AccessQuery query = new AccessQuery();
|
||||
query.setAccessIds(accessIds);
|
||||
List<AccessVO> accessList = selectAccessList(query);
|
||||
int delete = accessMapper.deleteAccessByAccessIds(accessIds);
|
||||
|
||||
// 清除缓存
|
||||
for (AccessVO access : accessList) {
|
||||
this.deleteCache(access.getAccessKey());
|
||||
}
|
||||
|
||||
return delete;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除第三方API秘钥对信息
|
||||
*
|
||||
* @param accessId 第三方API秘钥对主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteAccessByAccessId(Long accessId)
|
||||
{
|
||||
return accessMapper.deleteAccessByAccessId(accessId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessApplyVO apply(Long userId) {
|
||||
if (userId == null) {
|
||||
return null;
|
||||
}
|
||||
ServiceUtil.assertion(!redisLock.lock(RedisLockKey.APPLY_ACCESS, userId), "请勿重复提交申请");
|
||||
try {
|
||||
int count = this.selectCountByUserId(userId);
|
||||
ServiceUtil.assertion(count >= maxCount, "用户密钥对超过最大数量,最大允许数量:" + maxCount);
|
||||
|
||||
// 生成原始密钥对
|
||||
Access access = this.genAccess(userId);
|
||||
AccessApplyVO result = new AccessApplyVO(access);
|
||||
|
||||
// 加密秘钥
|
||||
access.setAccessSecret(SecurityUtils.encryptPassword(access.getAccessSecret()));
|
||||
// 插入加密后的秘钥
|
||||
int insert = this.insertAccess(access);
|
||||
ServiceUtil.assertion(insert != 1, "生成密钥对失败");
|
||||
|
||||
// 返回未加密的密钥对
|
||||
return result;
|
||||
} finally {
|
||||
redisLock.unlock(RedisLockKey.APPLY_ACCESS, userId);
|
||||
}
|
||||
}
|
||||
|
||||
// 生成一个密钥对
|
||||
private Access genAccess(Long userId) {
|
||||
if (userId == null) {
|
||||
return null;
|
||||
}
|
||||
Access access = new Access();
|
||||
access.setUserId(userId);
|
||||
access.setAccessKey(StringUtil.valueOf(SnowFlakeUtil.newId()));
|
||||
access.setAccessSecret(SecurityUtils.genSecret(64));
|
||||
return access;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int selectCountByUserId(Long userId) {
|
||||
if (userId == null) {
|
||||
return 0;
|
||||
}
|
||||
return accessMapper.selectCountByUserId(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SmUserVo selectUserByAccess(String accessKey) {
|
||||
AccessVO access = this.selectByAccessKey(accessKey);
|
||||
if (access == null) {
|
||||
return null;
|
||||
}
|
||||
return userService.selectSmUserByUserId(access.getUserId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessVO selectByAccessKey(String accessKey) {
|
||||
return accessMapper.selectByAccessKey(accessKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteCache(String accessKey) {
|
||||
if (StringUtils.isBlank(accessKey)) {
|
||||
return false;
|
||||
}
|
||||
return redisCache.deleteObject(CacheConstants.ACCESS_KEY_PREFIX + accessKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessApplyVO reset(Long accessId) {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -229,11 +229,10 @@ public class DeviceServiceImpl implements DeviceService
|
|||
}
|
||||
Map<Long, SmDeviceVO> deviceMap = selectMap(dto);
|
||||
|
||||
deviceAssembler.assembleTenant(new ArrayList<>(deviceMap.values()));
|
||||
for (Long deviceId : deviceIds) {
|
||||
SmDeviceVO device = deviceMap.get(deviceId);
|
||||
ServiceUtil.assertion(device == null, String.format("设备“%s”不存在,请刷新后重试", deviceId));
|
||||
ServiceUtil.assertion(!CollectionUtils.isEmpty(device.getTenantIds()), String.format("设备“%s”还有租户,请解绑后再进行删除", device.getDeviceName()));
|
||||
ServiceUtil.assertion(DeviceStatus.USING.getStatus().equals(device.getStatus()), String.format("设备“%s”正在使用中,无法删除", deviceId));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -264,18 +263,19 @@ public class DeviceServiceImpl implements DeviceService
|
|||
|
||||
|
||||
@Override
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public boolean addTimeByUser(Long deviceId, long seconds, boolean withIot, String reason) {
|
||||
boolean b = this.addTime(deviceId, seconds, withIot);
|
||||
boolean addTime = this.addTime(deviceId, seconds, withIot);
|
||||
|
||||
// 记录下操作日志
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
scheduledExecutorService.schedule(() -> {
|
||||
SmDeviceVO device = smDeviceMapper.selectSmDeviceByDeviceId(deviceId);
|
||||
recordTimeService.insertRecordTime(recordTimeConverter.toRecordTime(device, seconds, reason, loginUser));
|
||||
}, 0, TimeUnit.SECONDS);
|
||||
if (addTime) {
|
||||
// 记录下操作日志
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
scheduledExecutorService.schedule(() -> {
|
||||
SmDeviceVO device = smDeviceMapper.selectSmDeviceByDeviceId(deviceId);
|
||||
recordTimeService.insertRecordTime(recordTimeConverter.toRecordTime(device, seconds, reason, loginUser));
|
||||
}, 0, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
return b;
|
||||
return addTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -328,7 +328,6 @@ public class DeviceServiceImpl implements DeviceService
|
|||
|
||||
|
||||
@Override
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public boolean addTime(Long deviceId, long seconds, boolean withIot) {
|
||||
ServiceUtil.assertion( seconds < 0, "增加的时长不允许小于0");
|
||||
|
||||
|
@ -337,22 +336,26 @@ public class DeviceServiceImpl implements DeviceService
|
|||
ServiceUtil.assertion(!StringUtils.hasText(device.getMac()), "设备MAC号为空");
|
||||
ServiceUtil.assertion(DeviceStatus.FIXING.getStatus().equals(device.getStatus()), "设备正在维修中,无法使用");
|
||||
|
||||
// 更新数据库时长
|
||||
int updateCount = smDeviceMapper.addTime(deviceId, seconds);
|
||||
ServiceUtil.assertion(updateCount != 1, "增加时长失败,请刷新后重试");
|
||||
transactionTemplate.execute(status -> {
|
||||
// 更新数据库时长
|
||||
int updateCount = smDeviceMapper.addTime(deviceId, seconds);
|
||||
ServiceUtil.assertion(updateCount != 1, "增加时长失败,请刷新后重试");
|
||||
|
||||
// 修改状态为使用中
|
||||
changeStatus(deviceId, DeviceStatus.USING);
|
||||
// 修改状态为使用中
|
||||
changeStatus(deviceId, DeviceStatus.USING);
|
||||
|
||||
// 物联网设备增加时长
|
||||
if (withIot) {
|
||||
SmDeviceVO newDevice = selectSmDeviceByDeviceId(deviceId);
|
||||
long betweenSeconds = Duration.between(LocalDateTime.now(), newDevice.getExpireTime()).getSeconds();
|
||||
if (betweenSeconds > 0) {
|
||||
CommandResponse rechargeResult = iotService.setTime(device.getMac(), betweenSeconds);
|
||||
ServiceUtil.assertion(!rechargeResult.isSuccess(), "设备充值失败,请检查设备是否在线或联系管理员");
|
||||
// 物联网设备增加时长
|
||||
if (withIot) {
|
||||
SmDeviceVO newDevice = selectSmDeviceByDeviceId(deviceId);
|
||||
long betweenSeconds = Duration.between(LocalDateTime.now(), newDevice.getExpireTime()).getSeconds();
|
||||
if (betweenSeconds > 0) {
|
||||
CommandResponse rechargeResult = iotService.setTime(device.getMac(), betweenSeconds);
|
||||
ServiceUtil.assertion(!rechargeResult.isSuccess(), "设备充值失败,请检查设备是否在线或联系管理员");
|
||||
}
|
||||
}
|
||||
}
|
||||
return Boolean.TRUE;
|
||||
});
|
||||
|
||||
|
||||
// 拉取设备信息
|
||||
this.pullDeviceInfoAsync(Collections.singletonList(deviceId), 3, TimeUnit.SECONDS);
|
||||
|
@ -360,7 +363,7 @@ public class DeviceServiceImpl implements DeviceService
|
|||
// 时长结束后修改设备状态
|
||||
scheduledExecutorService.schedule(()-> {
|
||||
freshStatus(deviceId);
|
||||
}, seconds, TimeUnit.MINUTES);
|
||||
}, seconds, TimeUnit.SECONDS);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -634,12 +637,15 @@ public class DeviceServiceImpl implements DeviceService
|
|||
CommandResponse commandResponse = iotService.setTime(device.getMac(), 0L);
|
||||
ServiceUtil.assertion(!commandResponse.isSuccess(), "设备归零失败,请检查设备是否在线或联系管理员");
|
||||
|
||||
// 强制关闭
|
||||
iotService.close(device.getMac());
|
||||
|
||||
// 归零记录
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
scheduledExecutorService.schedule(() -> {
|
||||
// 设备剩余时长
|
||||
Duration duration = Duration.between(now, device.getExpireTime());
|
||||
recordTimeService.insertRecordTime(recordTimeConverter.toRecordTime(device, -duration.toMinutes(), "设备归零", loginUser));
|
||||
recordTimeService.insertRecordTime(recordTimeConverter.toRecordTime(device, -duration.getSeconds(), "设备归零", loginUser));
|
||||
}, 0, TimeUnit.SECONDS);
|
||||
|
||||
return true;
|
||||
|
|
|
@ -2,7 +2,9 @@ package com.ruoyi.ss.record.time.service;
|
|||
|
||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||
import com.ruoyi.ss.device.domain.SmDevice;
|
||||
import com.ruoyi.ss.device.domain.vo.SmDeviceVO;
|
||||
import com.ruoyi.ss.record.time.domain.RecordTime;
|
||||
import com.ruoyi.ss.user.domain.SmUserVo;
|
||||
|
||||
/**
|
||||
* @author wjh
|
||||
|
@ -12,4 +14,5 @@ public interface RecordTimeConverter {
|
|||
|
||||
RecordTime toRecordTime(SmDevice device, long seconds, String reason, LoginUser loginUser);
|
||||
|
||||
RecordTime toRecordTime(SmDeviceVO device, long secondSuitTime, String reason, SmUserVo user);
|
||||
}
|
||||
|
|
|
@ -3,9 +3,11 @@ package com.ruoyi.ss.record.time.service.impl;
|
|||
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||
import com.ruoyi.common.enums.LoginType;
|
||||
import com.ruoyi.ss.device.domain.SmDevice;
|
||||
import com.ruoyi.ss.device.domain.vo.SmDeviceVO;
|
||||
import com.ruoyi.ss.record.time.domain.RecordTime;
|
||||
import com.ruoyi.ss.record.time.domain.enums.OperatorType;
|
||||
import com.ruoyi.ss.record.time.service.RecordTimeConverter;
|
||||
import com.ruoyi.ss.user.domain.SmUserVo;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
@ -22,14 +24,31 @@ public class RecordTimeConverterImpl implements RecordTimeConverter {
|
|||
record.setDeviceId(device == null ? null : device.getDeviceId());
|
||||
record.setAmount(seconds);
|
||||
record.setReason(reason);
|
||||
record.setOperatorId(loginUser.getUserId());
|
||||
record.setOperatorName(loginUser.getUsername());
|
||||
record.setOperatorType(toOperatorType(loginUser.getLoginType()));
|
||||
if (loginUser != null) {
|
||||
record.setOperatorId(loginUser.getUserId());
|
||||
record.setOperatorName(loginUser.getUsername());
|
||||
record.setOperatorType(toOperatorType(loginUser.getLoginType()));
|
||||
}
|
||||
record.setOperatorTime(LocalDateTime.now());
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecordTime toRecordTime(SmDeviceVO device, long seconds, String reason, SmUserVo user) {
|
||||
RecordTime record = new RecordTime();
|
||||
record.setDeviceId(device == null ? null : device.getDeviceId());
|
||||
record.setAmount(seconds);
|
||||
record.setReason(reason);
|
||||
if (user != null) {
|
||||
record.setOperatorId(user.getUserId());
|
||||
record.setOperatorName(user.getUserName());
|
||||
record.setOperatorType(OperatorType.USER.getType());
|
||||
}
|
||||
record.setOperatorTime(LocalDateTime.now());
|
||||
return record;
|
||||
}
|
||||
|
||||
private String toOperatorType(LoginType loginType) {
|
||||
return OperatorType.parse(loginType).getType();
|
||||
}
|
||||
|
|
|
@ -77,4 +77,7 @@ public class Suit extends BaseEntity
|
|||
@NotBlank(message = "套餐时长单位不允许为空", groups = {ValidGroup.Create.class, ValidGroup.FrontCreate.class})
|
||||
@DictValid(type = DictTypeConstants.SUIT_TIME_UNIT, message = "非法的套餐时长单位")
|
||||
private String timeUnit;
|
||||
|
||||
@ApiModelProperty("用户ID")
|
||||
private Long userId;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ public class SuitBO extends Suit {
|
|||
bo.setPrice(getPrice());
|
||||
bo.setDescription(getDescription());
|
||||
bo.setTimeUnit(getTimeUnit());
|
||||
bo.setUserId(getUserId());
|
||||
return bo;
|
||||
}
|
||||
|
||||
|
@ -31,7 +32,6 @@ public class SuitBO extends Suit {
|
|||
public SuitBO filterUpdateByApp() {
|
||||
SuitBO bo = new SuitBO();
|
||||
bo.setSuitId(getSuitId());
|
||||
bo.setDeviceId(getDeviceId());
|
||||
bo.setName(getName());
|
||||
bo.setValue(getValue());
|
||||
bo.setPrice(getPrice());
|
||||
|
|
|
@ -21,6 +21,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
ss.deleted,
|
||||
ss.source_id,
|
||||
ss.time_unit,
|
||||
ss.user_id,
|
||||
sd.device_name as device_name,
|
||||
su.user_name as user_name,
|
||||
store.name as store_name
|
||||
|
@ -41,7 +42,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<if test="deleted == null"> and ss.deleted = false</if>
|
||||
<if test="deleted != null"> and ss.deleted = #{deleted}</if>
|
||||
<if test="deviceName != null"> and sd.device_name like concat('%', #{deviceName}, '%')</if>
|
||||
<if test="mchId != null"> and sd.user_id = #{mchId}</if>
|
||||
<if test="mchId != null"> and ss.user_id = #{mchId}</if>
|
||||
<if test="userId != null"> and ss.user_id = #{userId}</if>
|
||||
<if test="needSource != null">
|
||||
<if test="needSource">
|
||||
and ss.source_id is not null
|
||||
|
@ -104,6 +106,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<if test="deleted != null">deleted,</if>
|
||||
<if test="sourceId != null">source_id,</if>
|
||||
<if test="timeUnit != null">time_unit,</if>
|
||||
<if test="userId != null">user_id,</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="deviceId != null">#{deviceId},</if>
|
||||
|
@ -118,6 +121,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<if test="deleted != null">#{deleted},</if>
|
||||
<if test="sourceId != null">#{sourceId},</if>
|
||||
<if test="timeUnit != null">#{timeUnit},</if>
|
||||
<if test="userId != null">#{userId},</if>
|
||||
</trim>
|
||||
</insert>
|
||||
|
||||
|
@ -133,11 +137,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
update_time,
|
||||
update_by,
|
||||
deleted,
|
||||
source_id
|
||||
source_id,
|
||||
time_unit,
|
||||
user_id
|
||||
)
|
||||
values
|
||||
<foreach collection="list" item="i" separator=",">
|
||||
<trim prefix="(" suffix=")">
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="i.deviceId != null">#{i.deviceId},</if>
|
||||
<if test="i.deviceId == null">default,</if>
|
||||
<if test="i.name != null and i.name != ''">#{i.name},</if>
|
||||
|
@ -158,10 +164,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<if test="i.updateBy == null">default,</if>
|
||||
<if test="i.deleted != null">#{i.deleted},</if>
|
||||
<if test="i.deleted == null">default,</if>
|
||||
<if test="i.sourceId != null">#{i.sourceId}</if>
|
||||
<if test="i.sourceId != null">#{i.sourceId},</if>
|
||||
<if test="i.sourceId == null">default,</if>
|
||||
<if test="i.timeUnit != null">#{i.timeUnit}</if>
|
||||
<if test="i.timeUnit != null">#{i.timeUnit},</if>
|
||||
<if test="i.timeUnit == null">default,</if>
|
||||
<if test="i.userId != null">#{i.userId},</if>
|
||||
<if test="i.userId == null">default,</if>
|
||||
</trim>
|
||||
</foreach>
|
||||
|
||||
|
@ -185,6 +193,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<if test="updateBy != null">update_by = #{updateBy},</if>
|
||||
<if test="sourceId != null">source_id = #{sourceId},</if>
|
||||
<if test="timeUnit != null">time_unit = #{timeUnit},</if>
|
||||
<if test="userId != null">user_id = #{userId},</if>
|
||||
</sql>
|
||||
|
||||
<update id="logicDel">
|
||||
|
|
|
@ -50,6 +50,8 @@ public class SuitConverterImpl implements SuitConverter {
|
|||
data.setPrice(suit.getPrice());
|
||||
data.setDescription(suit.getDescription());
|
||||
data.setSourceId(suit.getSuitId());
|
||||
data.setTimeUnit(suit.getTimeUnit());
|
||||
data.setUserId(suit.getUserId());
|
||||
list.add(data);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.springframework.transaction.support.TransactionTemplate;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
@ -184,7 +185,9 @@ public class SuitServiceImpl implements SuitService
|
|||
if (CollectionUtils.isEmptyElement(list)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
return list.stream().collect(Collectors.groupingBy(keyMapper));
|
||||
return list.stream()
|
||||
.filter(item -> Objects.nonNull(keyMapper.apply(item)))
|
||||
.collect(Collectors.groupingBy(keyMapper));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -136,15 +136,19 @@ public class TransactionBill extends BaseEntity
|
|||
@ApiModelProperty("套餐时长单位")
|
||||
@NotBlank(message = "套餐时长单位不允许为空", groups = {ValidGroup.Recharge.class})
|
||||
@DictValid(type = DictTypeConstants.SUIT_TIME_UNIT, message = "非法的套餐时长单位", groups = {ValidGroup.Recharge.class})
|
||||
@JsonView(JsonViewProfile.AppUser.class)
|
||||
private String suitTimeUnit;
|
||||
|
||||
@ApiModelProperty("套餐开始使用时间")
|
||||
@JsonView(JsonViewProfile.App.class)
|
||||
private LocalDateTime suitStartTime;
|
||||
|
||||
@ApiModelProperty("套餐结束使用时间")
|
||||
@JsonView(JsonViewProfile.App.class)
|
||||
private LocalDateTime suitEndTime;
|
||||
|
||||
@ApiModelProperty("套餐到期时间")
|
||||
@JsonView(JsonViewProfile.App.class)
|
||||
private LocalDateTime suitExpireTime;
|
||||
|
||||
@ApiModelProperty("店铺ID")
|
||||
|
|
|
@ -32,6 +32,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
stb.device_recharge_status,
|
||||
stb.suit_id,
|
||||
stb.suit_time,
|
||||
stb.suit_time_unit,
|
||||
stb.suit_start_time,
|
||||
stb.suit_end_time,
|
||||
stb.suit_expire_time,
|
||||
|
@ -218,6 +219,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<if test="deviceRechargeStatus != null ">device_recharge_status,</if>
|
||||
<if test="suitId != null ">suit_id,</if>
|
||||
<if test="suitTime != null ">suit_time,</if>
|
||||
<if test="suitTimeUnit != null ">suit_time_unit,</if>
|
||||
<if test="suitStartTime != null ">suit_start_time,</if>
|
||||
<if test="suitEndTime != null ">suit_end_time,</if>
|
||||
<if test="suitExpireTime != null ">suit_expire_time,</if>
|
||||
|
@ -255,6 +257,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<if test="deviceRechargeStatus != null">#{deviceRechargeStatus},</if>
|
||||
<if test="suitId != null">#{suitId},</if>
|
||||
<if test="suitTime != null">#{suitTime},</if>
|
||||
<if test="suitTimeUnit != null">#{suitTimeUnit},</if>
|
||||
<if test="suitStartTime != null">#{suitStartTime},</if>
|
||||
<if test="suitEndTime != null">#{suitEndTime},</if>
|
||||
<if test="suitExpireTime != null">#{suitExpireTime},</if>
|
||||
|
@ -309,6 +312,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<if test="data.channelCost != null">channel_cost = #{data.channelCost},</if>
|
||||
<if test="data.suitId != null">suit_id = #{data.suitId},</if>
|
||||
<if test="data.suitTime != null">suit_time = #{data.suitTime},</if>
|
||||
<if test="data.suitTimeUnit != null">suit_time_unit = #{data.suitTimeUnit},</if>
|
||||
<if test="data.suitStartTime != null">suit_start_time = #{data.suitStartTime},</if>
|
||||
<if test="data.suitEndTime != null">suit_end_time = #{data.suitEndTime},</if>
|
||||
<if test="data.suitExpireTime != null">suit_expire_time = #{data.suitExpireTime},</if>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package com.ruoyi.ss.transactionBill.service.impl;
|
||||
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||
import com.ruoyi.common.core.redis.RedisLock;
|
||||
import com.ruoyi.common.core.redis.enums.RedisLockKey;
|
||||
import com.ruoyi.common.exception.ServiceException;
|
||||
|
@ -46,8 +45,6 @@ import lombok.extern.slf4j.Slf4j;
|
|||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Isolation;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
|
@ -547,34 +544,50 @@ public class TransactionBillServiceImpl implements TransactionBillService {
|
|||
* @param billId
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public boolean rechargeDevice(Long billId) {
|
||||
ServiceUtil.assertion(billId == null, "参数错误,billId不允许为空");
|
||||
|
||||
TransactionBillVo bill = transactionBillMapper.selectSmTransactionBillByBillId(billId);
|
||||
|
||||
ServiceUtil.assertion(bill == null || !TransactionBillType.RECHARGE.getType().equals(bill.getType()), "不存在的充值订单");
|
||||
ServiceUtil.assertion(!TransactionBillStatus.SUCCESS.getStatus().equals(bill.getStatus()), "订单未支付");
|
||||
ServiceUtil.assertion(TransactionBillDeviceRechargeStatus.SUCCESS.getStatus().equals(bill.getDeviceRechargeStatus()), "设备已充值成功,不允许再次充值");
|
||||
ServiceUtil.assertion(TransactionBillDeviceRechargeStatus.BLUETOOTH.getStatus().equals(bill.getDeviceRechargeStatus()), "设备已选择蓝牙充值,请使用蓝牙进行充值");
|
||||
|
||||
// 电表时长增加,四舍五入,保留1位小数
|
||||
boolean success = false;
|
||||
ServiceUtil.assertion(!redisLock.lock(RedisLockKey.RECHARGE_DEVICE, billId), "当前设备充值请求过于频繁,请等待");
|
||||
try {
|
||||
success = deviceService.addTime(bill.getDeviceId(), bill.toSecondSuitTime(), true);
|
||||
} catch (Exception e) {
|
||||
this.handleDeviceRechargeFail(billId);
|
||||
TransactionBillVo bill = transactionBillMapper.selectSmTransactionBillByBillId(billId);
|
||||
ServiceUtil.assertion(bill == null || !TransactionBillType.RECHARGE.getType().equals(bill.getType()), "不存在的充值订单");
|
||||
ServiceUtil.assertion(!TransactionBillStatus.SUCCESS.getStatus().equals(bill.getStatus()), "订单未支付");
|
||||
ServiceUtil.assertion(TransactionBillDeviceRechargeStatus.SUCCESS.getStatus().equals(bill.getDeviceRechargeStatus()), "设备已充值成功,不允许再次充值");
|
||||
ServiceUtil.assertion(TransactionBillDeviceRechargeStatus.BLUETOOTH.getStatus().equals(bill.getDeviceRechargeStatus()), "设备已选择蓝牙充值,请使用蓝牙进行充值");
|
||||
|
||||
Boolean result = transactionTemplate.execute(status -> {
|
||||
// 更新套餐生效时间
|
||||
SmDeviceVO device = deviceService.selectSmDeviceByDeviceId(bill.getDeviceId());
|
||||
this.updateSuitTimeBeforeDevice(billId, device.getExpireTime());
|
||||
|
||||
// 修改设备充值状态:成功
|
||||
int updateRecharge = transactionBillMapper.updateDeviceRechargeStatus(bill.getBillId(), TransactionBillDeviceRechargeStatus.SUCCESS.getStatus());
|
||||
ServiceUtil.assertion(updateRecharge != 1, "订单状态发生变化,请稍后重试");
|
||||
|
||||
try {
|
||||
// 设备充值
|
||||
return deviceService.addTime(bill.getDeviceId(), bill.toSecondSuitTime(), true);
|
||||
} catch (Exception e) {
|
||||
// 失败,回滚
|
||||
status.setRollbackOnly();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// 是否成功
|
||||
boolean success = result != null && result;
|
||||
|
||||
if (success) {
|
||||
// 记录时长变化
|
||||
this.recordTime(bill, "用户充值");
|
||||
} else {
|
||||
// 修改设备充值状态为失败
|
||||
transactionBillMapper.updateDeviceRechargeStatus(billId, TransactionBillDeviceRechargeStatus.FAIL.getStatus());
|
||||
}
|
||||
|
||||
return success;
|
||||
} finally {
|
||||
redisLock.unlock(RedisLockKey.RECHARGE_DEVICE, billId);
|
||||
}
|
||||
|
||||
// 修改设备充值状态:成功
|
||||
if (success) {
|
||||
SmDeviceVO device = deviceService.selectSmDeviceByDeviceId(bill.getDeviceId());
|
||||
this.updateSuitTimeBeforeDevice(billId, device.getExpireTime());
|
||||
|
||||
transactionBillMapper.updateDeviceRechargeStatus(bill.getBillId(), TransactionBillDeviceRechargeStatus.SUCCESS.getStatus());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -588,7 +601,7 @@ public class TransactionBillServiceImpl implements TransactionBillService {
|
|||
}
|
||||
// 计算开始使用的时间
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
LocalDateTime startTime = now.isAfter(deviceExpireTime) ? now : deviceExpireTime;
|
||||
LocalDateTime startTime = deviceExpireTime == null || now.isAfter(deviceExpireTime) ? now : deviceExpireTime;
|
||||
|
||||
LocalDateTime endTime = startTime.plusSeconds(bill.toSecondSuitTime());
|
||||
TransactionBill data = new TransactionBill();
|
||||
|
@ -599,22 +612,12 @@ public class TransactionBillServiceImpl implements TransactionBillService {
|
|||
return transactionBillMapper.updateSmTransactionBill(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理设备充值失败
|
||||
*/
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.READ_COMMITTED)
|
||||
public void handleDeviceRechargeFail(Long billId) {
|
||||
// 修改设备充值状态为失败
|
||||
transactionBillMapper.updateDeviceRechargeStatus(billId, TransactionBillDeviceRechargeStatus.FAIL.getStatus());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取支付结果
|
||||
* @param billNo 订单编号
|
||||
* @return 支付结果
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public boolean getPayResult(String billNo) {
|
||||
// 查询订单
|
||||
TransactionBill bill = transactionBillMapper.selectSmTransactionBillByBillNo(billNo);
|
||||
|
@ -635,26 +638,30 @@ public class TransactionBillServiceImpl implements TransactionBillService {
|
|||
* @param billNo 充值订单编号
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public void rechargeSuccess(String billNo, Date payTime) {
|
||||
log.info("充值成功,billNo:{}", billNo);
|
||||
TransactionBill bill = transactionBillMapper.selectSmTransactionBillByBillNo(billNo);
|
||||
ServiceUtil.assertion(bill == null || !TransactionBillType.RECHARGE.getType().equals(bill.getType()), "充值订单不存在");
|
||||
|
||||
// 修改订单状态
|
||||
int updateCount = transactionBillMapper.rechargeSuccess(bill.getBillId(), payTime);
|
||||
ServiceUtil.assertion(updateCount != 1, "修改订单状态失败,请刷新后重试");
|
||||
Integer result = transactionTemplate.execute(status -> {
|
||||
// 修改订单状态
|
||||
int updateCount = transactionBillMapper.rechargeSuccess(bill.getBillId(), payTime);
|
||||
ServiceUtil.assertion(updateCount != 1, "修改订单状态失败,请刷新后重试");
|
||||
|
||||
// 商户余额增加
|
||||
userService.addBalance(bill.getMchId(), bill.getArrivalAmount());
|
||||
// 商户余额增加
|
||||
userService.addBalance(bill.getMchId(), bill.getArrivalAmount());
|
||||
|
||||
// 记录下充值后的余额
|
||||
SmUserVo user = userService.selectSmUserByUserId(bill.getMchId());
|
||||
updateAfterBalance(bill.getBillId(), user.getBalance());
|
||||
// 记录下充值后的余额
|
||||
SmUserVo user = userService.selectSmUserByUserId(bill.getMchId());
|
||||
updateAfterBalance(bill.getBillId(), user.getBalance());
|
||||
|
||||
// 设备充值
|
||||
rechargeDevice(bill.getBillId());
|
||||
return updateCount;
|
||||
});
|
||||
|
||||
if (result != null && result == 1) {
|
||||
// 设备充值
|
||||
rechargeDevice(bill.getBillId());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -753,7 +760,6 @@ public class TransactionBillServiceImpl implements TransactionBillService {
|
|||
* @param timeUnit 时间单位
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public void refreshPayResultBeforeExpire(String billNo, int delay, TimeUnit timeUnit) {
|
||||
TransactionBill bill = transactionBillMapper.selectSmTransactionBillByBillNo(billNo);
|
||||
if (bill == null) {
|
||||
|
@ -833,14 +839,15 @@ public class TransactionBillServiceImpl implements TransactionBillService {
|
|||
* @return
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public boolean bluetoothRechargeSuccess(String billNo) {
|
||||
TransactionBillVo bill = selectSmTransactionBillByBillNo(billNo);
|
||||
ServiceUtil.assertion(bill == null, "订单不存在", 10001);
|
||||
ServiceUtil.assertion(!TransactionBillType.RECHARGE.getType().equals(bill.getType()), "该订单不是充值订单", 10002);
|
||||
ServiceUtil.assertion(TransactionBillDeviceRechargeStatus.SUCCESS.getStatus().equals(bill.getDeviceRechargeStatus()), "设备已充值成功,请勿重复充值", 10003);
|
||||
ServiceUtil.assertion(!TransactionBillStatus.SUCCESS.getStatus().equals(bill.getStatus()), "订单尚未充值成功", 10004);
|
||||
|
||||
Boolean execute = transactionTemplate.execute(status -> {
|
||||
TransactionBillVo bill = selectSmTransactionBillByBillNo(billNo);
|
||||
ServiceUtil.assertion(bill == null, "订单不存在", 10001);
|
||||
ServiceUtil.assertion(!TransactionBillType.RECHARGE.getType().equals(bill.getType()), "该订单不是充值订单", 10002);
|
||||
ServiceUtil.assertion(TransactionBillDeviceRechargeStatus.SUCCESS.getStatus().equals(bill.getDeviceRechargeStatus()), "设备已充值成功,请勿重复充值", 10003);
|
||||
ServiceUtil.assertion(!TransactionBillStatus.SUCCESS.getStatus().equals(bill.getStatus()), "订单尚未充值成功", 10004);
|
||||
// 更新设备充值状态
|
||||
boolean result = transactionBillMapper.bluetoothRechargeSuccess(billNo) == 1;
|
||||
ServiceUtil.assertion(!result, "蓝牙充值回调失败");
|
||||
|
||||
|
@ -848,24 +855,34 @@ public class TransactionBillServiceImpl implements TransactionBillService {
|
|||
SmDeviceVO afterDevice = deviceService.selectSmDeviceByDeviceId(bill.getDeviceId());
|
||||
this.updateSuitTimeBeforeDevice(bill.getBillId(), afterDevice.getExpireTime());
|
||||
|
||||
// 修改剩余时间失败
|
||||
boolean addTime = deviceService.addTime(bill.getDeviceId(), bill.toSecondSuitTime(), false);
|
||||
ServiceUtil.assertion(!addTime, "修改剩余时间失败");
|
||||
|
||||
// 时长变化记录
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
scheduledExecutorService.schedule(() -> {
|
||||
SmDeviceVO device = deviceService.selectSmDeviceByDeviceId(bill.getDeviceId());
|
||||
if (device == null) {
|
||||
return;
|
||||
}
|
||||
recordTimeService.insertRecordTime(recordTimeConverter.toRecordTime(device, bill.getSuitTime(), "蓝牙手动充值", loginUser));
|
||||
}, 1L, TimeUnit.SECONDS);
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
// 是否成功
|
||||
boolean success = execute != null && execute;
|
||||
// 成功后操作
|
||||
if (success) {
|
||||
// 时长变化记录
|
||||
this.recordTime(bill, "蓝牙手动充值");
|
||||
}
|
||||
|
||||
return execute != null && execute;
|
||||
return success;
|
||||
}
|
||||
|
||||
// 记录时长变化记录
|
||||
private void recordTime(TransactionBillVo bill, String reason) {
|
||||
scheduledExecutorService.schedule(() -> {
|
||||
SmDeviceVO device = deviceService.selectSmDeviceByDeviceId(bill.getDeviceId());
|
||||
if (device == null) {
|
||||
return;
|
||||
}
|
||||
SmUserVo user = userService.selectSmUserByUserId(bill.getUserId());
|
||||
recordTimeService.insertRecordTime(recordTimeConverter.toRecordTime(device, bill.toSecondSuitTime(), reason, user));
|
||||
}, 1L, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -928,7 +945,6 @@ public class TransactionBillServiceImpl implements TransactionBillService {
|
|||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public int refreshPayResult(List<TransactionBillVo> billList) {
|
||||
if (CollectionUtils.isEmptyElement(billList)) {
|
||||
return 0;
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.ruoyi.ss.user.service;
|
|||
|
||||
import com.ruoyi.common.core.domain.entity.SmUser;
|
||||
import com.ruoyi.common.enums.UserType;
|
||||
import com.ruoyi.ss.access.domain.AccessVO;
|
||||
import com.ruoyi.ss.user.domain.SmUserQuery;
|
||||
import com.ruoyi.ss.user.domain.SmUserVo;
|
||||
import com.ruoyi.ss.user.domain.bo.UserUpdateServiceRateBO;
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package com.ruoyi.ss.user.service.impl;
|
||||
|
||||
import com.ruoyi.common.constant.CacheConstants;
|
||||
import com.ruoyi.common.core.domain.entity.SmUser;
|
||||
import com.ruoyi.common.core.redis.RedisCache;
|
||||
import com.ruoyi.common.enums.UserType;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
|
|
|
@ -182,7 +182,6 @@ public class WxPayService implements IWxPayService {
|
|||
* @param request 请求
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public void payNotify(HttpServletRequest request) {
|
||||
// 获取原始报文body
|
||||
String body = HttpUtils.getBody(request);
|
||||
|
@ -199,8 +198,6 @@ public class WxPayService implements IWxPayService {
|
|||
if (Transaction.TradeStateEnum.SUCCESS.equals(transaction.getTradeState())) {
|
||||
// 充值成功,修改订单状态
|
||||
transactionBillService.rechargeSuccess(transaction.getOutTradeNo(), DateUtils.getNowDate());
|
||||
// 保存通知数据
|
||||
// saveNotifyData(transaction.getOutTradeNo(), notification, transaction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,7 +59,6 @@ public class BillDelayed implements Delayed {
|
|||
/**
|
||||
* 执行删除订单任务
|
||||
*/
|
||||
@Transactional
|
||||
public void run() {
|
||||
log.info("执行订单超时任务:" + billNo);
|
||||
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
package com.ruoyi.web.controller.api;
|
||||
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.framework.web.service.SysLoginService;
|
||||
import com.ruoyi.ss.access.domain.AccessVO;
|
||||
import com.ruoyi.ss.access.service.AccessService;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/**
|
||||
* 第三方认证接口
|
||||
* @author wjh
|
||||
* 2024/7/17
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/openapi/v1/access")
|
||||
public class ApiAccessController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private AccessService accessService;
|
||||
|
||||
@ApiOperation("申请accessKey")
|
||||
@PostMapping
|
||||
public AjaxResult apply() {
|
||||
return success(accessService.apply(getUserId()));
|
||||
}
|
||||
|
||||
@ApiOperation("重置accessSecret")
|
||||
@PutMapping("/{accessId}/reset")
|
||||
public AjaxResult reset(@PathVariable Long accessId) {
|
||||
AccessVO access = accessService.selectAccessByAccessId(accessId);
|
||||
return success(accessService.reset(accessId));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package com.ruoyi.web.controller.api;
|
||||
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* 第三方API 设备Controller
|
||||
* @author wjh
|
||||
* 2024/7/17
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/openapi/v1/device")
|
||||
public class ApiDeviceController {
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -87,7 +87,7 @@ public class AppDeviceController extends BaseController {
|
|||
@ApiOperation("获取设备详细信息")
|
||||
@GetMapping(value = "/{deviceId}")
|
||||
public AjaxResult getInfo(@PathVariable("deviceId") Long deviceId) {
|
||||
// ServiceUtil.assertion(!deviceValidator.isBelong(deviceId, getUserId()), "这不是您的设备");
|
||||
smDeviceService.pullDeviceInfo(Collections.singletonList(deviceId));
|
||||
SmDeviceVO device = smDeviceService.selectSmDeviceByDeviceId(deviceId);
|
||||
List<SmDeviceVO> list = Collections.singletonList(device);
|
||||
deviceAssembler.assembleOrderCountInfo(list); // 订单统计信息
|
||||
|
@ -137,13 +137,12 @@ public class AppDeviceController extends BaseController {
|
|||
|
||||
@ApiOperation("设备充值时长")
|
||||
@PutMapping("/addTime/{deviceId}")
|
||||
public AjaxResult addTime(@PathVariable @ApiParam("设备id") Long deviceId, @ApiParam("电量(度)") Long amount)
|
||||
public AjaxResult addTime(@PathVariable @ApiParam("设备id") Long deviceId, @ApiParam("时长(分钟)") Long amount)
|
||||
{
|
||||
ServiceUtil.assertion(!deviceValidator.isBelong(deviceId, getUserId()), "这不是您的设备");
|
||||
SmDeviceVO device = smDeviceService.selectSmDeviceByDeviceId(deviceId);
|
||||
ServiceUtil.assertion(device == null || !getUserId().equals(device.getUserId()), "设备不存在或您无权充值");
|
||||
smDeviceService.addTimeByUser(deviceId, amount, true, "商户手动充值");
|
||||
return success(true);
|
||||
return toAjax(smDeviceService.addTimeByUser(deviceId, amount * 60, true, "商户手动充值"));
|
||||
}
|
||||
|
||||
@ApiOperation("刷新设备信息")
|
||||
|
|
|
@ -72,6 +72,7 @@ public class AppSuitController extends BaseController {
|
|||
@ApiOperation("新增套餐")
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody @Validated({ValidGroup.FrontCreate.class}) SuitBO suit) {
|
||||
suit.setUserId(getUserId());
|
||||
suit = suit.filterCreateByApp();
|
||||
ServiceUtil.assertion(suitValidator.preCreateByApp(suit));
|
||||
return success(suitService.insertSuit(suit));
|
||||
|
@ -85,8 +86,7 @@ public class AppSuitController extends BaseController {
|
|||
|
||||
@ApiOperation("修改套餐")
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody @Validated({ValidGroup.FrontUpdate.class}) SuitBO suit)
|
||||
{
|
||||
public AjaxResult edit(@RequestBody @Validated({ValidGroup.FrontUpdate.class}) SuitBO suit) {
|
||||
suit = suit.filterUpdateByApp();
|
||||
ServiceUtil.assertion(suitValidator.preUpdateByApp(suit));
|
||||
return success(suitService.updateSuit(suit));
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
package com.ruoyi.web.controller.ss;
|
||||
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.ruoyi.ss.access.domain.AccessQuery;
|
||||
import com.ruoyi.ss.access.domain.AccessVO;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.ss.access.domain.Access;
|
||||
import com.ruoyi.ss.access.service.AccessService;
|
||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
|
||||
/**
|
||||
* 第三方API秘钥对Controller
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2024-07-17
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/ss/access")
|
||||
public class AccessController extends BaseController
|
||||
{
|
||||
@Autowired
|
||||
private AccessService accessService;
|
||||
|
||||
/**
|
||||
* 查询第三方API秘钥对列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('ss:access:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(AccessQuery query)
|
||||
{
|
||||
startPage();
|
||||
List<AccessVO> list = accessService.selectAccessList(query);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出第三方API秘钥对列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('ss:access:export')")
|
||||
@Log(title = "第三方API秘钥对", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(HttpServletResponse response, AccessQuery query)
|
||||
{
|
||||
List<AccessVO> list = accessService.selectAccessList(query);
|
||||
ExcelUtil<AccessVO> util = new ExcelUtil<AccessVO>(AccessVO.class);
|
||||
util.exportExcel(response, list, "第三方API秘钥对数据");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取第三方API秘钥对详细信息
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('ss:access:query')")
|
||||
@GetMapping(value = "/{accessId}")
|
||||
public AjaxResult getInfo(@PathVariable("accessId") Long accessId)
|
||||
{
|
||||
return success(accessService.selectAccessByAccessId(accessId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增第三方API秘钥对
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('ss:access:add')")
|
||||
@Log(title = "第三方API秘钥对", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody Access access)
|
||||
{
|
||||
return toAjax(accessService.insertAccess(access));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改第三方API秘钥对
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('ss:access:edit')")
|
||||
@Log(title = "第三方API秘钥对", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody Access access)
|
||||
{
|
||||
return toAjax(accessService.updateAccess(access));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除第三方API秘钥对
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('ss:access:remove')")
|
||||
@Log(title = "第三方API秘钥对", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{accessIds}")
|
||||
public AjaxResult remove(@PathVariable List<Long> accessIds)
|
||||
{
|
||||
return toAjax(accessService.deleteAccessByAccessIds(accessIds));
|
||||
}
|
||||
}
|
|
@ -86,6 +86,7 @@ public class SmDeviceController extends BaseController
|
|||
@GetMapping(value = "/{deviceId}")
|
||||
public AjaxResult getInfo(@PathVariable("deviceId") Long deviceId)
|
||||
{
|
||||
smDeviceService.pullDeviceInfo(Collections.singletonList(deviceId));
|
||||
SmDeviceVO device = smDeviceService.selectSmDeviceByDeviceId(deviceId);
|
||||
List<SmDeviceVO> list = Collections.singletonList(device);
|
||||
deviceAssembler.assembleIotDeviceInfo(list);
|
||||
|
@ -153,8 +154,8 @@ public class SmDeviceController extends BaseController
|
|||
@ApiOperation("设备充值时长")
|
||||
@PreAuthorize("@ss.hasPermi('system:device:addTime')")
|
||||
@PutMapping("/addTime/{deviceId}")
|
||||
public AjaxResult addTime(@PathVariable @ApiParam("设备id") Long deviceId, @ApiParam("时长(秒)") Long amount) {
|
||||
return toAjax(smDeviceService.addTimeByUser(deviceId, amount, true, "管理员手动充值"));
|
||||
public AjaxResult addTime(@PathVariable @ApiParam("设备id") Long deviceId, @ApiParam("时长(分)") Long amount) {
|
||||
return toAjax(smDeviceService.addTimeByUser(deviceId, amount * 60, true, "管理员手动充值"));
|
||||
}
|
||||
|
||||
@ApiOperation("设备时长归零")
|
||||
|
|
|
@ -159,10 +159,8 @@ public class SmTransactionBillController extends BaseController
|
|||
@ApiModelProperty("手动设备充值")
|
||||
@GetMapping("/rechargeDevice/{billId}")
|
||||
@Log(title = "手动设备充值", businessType = BusinessType.UPDATE)
|
||||
public AjaxResult rechargeDevice(@PathVariable Long billId)
|
||||
{
|
||||
smTransactionBillService.rechargeDevice(billId);
|
||||
return success();
|
||||
public AjaxResult rechargeDevice(@PathVariable Long billId) {
|
||||
return toAjax(smTransactionBillService.rechargeDevice(billId));
|
||||
}
|
||||
|
||||
// 订单退款
|
||||
|
|
|
@ -6,6 +6,8 @@ import javax.servlet.http.HttpServletResponse;
|
|||
|
||||
import com.ruoyi.common.core.domain.ValidGroup;
|
||||
import com.ruoyi.common.utils.ServiceUtil;
|
||||
import com.ruoyi.ss.device.domain.vo.SmDeviceVO;
|
||||
import com.ruoyi.ss.device.service.DeviceService;
|
||||
import com.ruoyi.ss.suit.domain.SuitBO;
|
||||
import com.ruoyi.ss.suit.domain.SuitQuery;
|
||||
import com.ruoyi.ss.suit.domain.SuitVo;
|
||||
|
@ -46,6 +48,9 @@ public class SuitController extends BaseController
|
|||
@Autowired
|
||||
private SuitValidator suitValidator;
|
||||
|
||||
@Autowired
|
||||
private DeviceService deviceService;
|
||||
|
||||
/**
|
||||
* 查询套餐列表
|
||||
*/
|
||||
|
@ -89,6 +94,11 @@ public class SuitController extends BaseController
|
|||
@PostMapping
|
||||
public AjaxResult add(@RequestBody @Validated(ValidGroup.Create.class) SuitBO suit)
|
||||
{
|
||||
SmDeviceVO device = deviceService.selectSmDeviceByDeviceId(suit.getDeviceId());
|
||||
if (device == null) {
|
||||
return error("设备不存在");
|
||||
}
|
||||
suit.setUserId(device.getUserId());
|
||||
return toAjax(suitService.insertSuit(suit));
|
||||
}
|
||||
|
||||
|
@ -98,7 +108,7 @@ public class SuitController extends BaseController
|
|||
@PreAuthorize("@ss.hasPermi('ss:suit:edit')")
|
||||
@Log(title = "套餐", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody @Validated(ValidGroup.Update.class) Suit suit)
|
||||
public AjaxResult edit(@RequestBody @Validated(ValidGroup.Update.class) SuitBO suit)
|
||||
{
|
||||
return toAjax(suitService.updateSuit(suit));
|
||||
}
|
||||
|
|
|
@ -177,3 +177,8 @@ sm:
|
|||
withdraw:
|
||||
password:
|
||||
enable: false
|
||||
|
||||
# 对外API设置
|
||||
access:
|
||||
# 用户最大密钥对数量
|
||||
maxCount: 1
|
||||
|
|
Loading…
Reference in New Issue
Block a user