风控提交

This commit is contained in:
磷叶 2024-11-25 18:01:55 +08:00
parent 1c8a9d78de
commit d2e00163bd
44 changed files with 1281 additions and 214 deletions

View File

@ -17,6 +17,13 @@
<dependencies>
<!--支付宝SDK-->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.34.0.ALL</version>
</dependency>
<!--阿里云短信发送start-->
<!--阿里云发送短信-->
<dependency>

View File

@ -0,0 +1,15 @@
package com.ruoyi.common.auth.ali;
import org.springframework.stereotype.Service;
/**
* 支付宝认证服务
* @author wjh
* 2024/11/25
*/
@Service
public class AliAuthService {
}

View File

@ -0,0 +1,32 @@
package com.ruoyi.common.auth.ali;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayConfig;
import com.alipay.api.DefaultAlipayClient;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
/**
* @author wjh
* 2024/11/25
*/
@Component
@Data
public class AliConfig {
// @Value("${ali.appId}")
// private String appId;
//
// @Value("${ali.privateKey}")
// private String privateKey;
//
// @Bean
// public AlipayConfig alipayConfig() {
// AlipayConfig config = new AlipayConfig();
// config.setAppId(appId);
// config.setPrivateKey(privateKey);
// return config;
// }
}

View File

@ -23,7 +23,7 @@ import com.ruoyi.common.utils.sql.SqlUtil;
/**
* web层通用数据处理
*
*
* @author ruoyi
*/
public class BaseController
@ -113,7 +113,7 @@ public class BaseController
{
return AjaxResult.success(message);
}
/**
* 返回成功消息
*/
@ -127,7 +127,7 @@ public class BaseController
*/
public AjaxResult error(String message)
{
return AjaxResult.error(message);
return AjaxResult.error(message, null);
}
/**
@ -140,7 +140,7 @@ public class BaseController
/**
* 响应返回结果
*
*
* @param rows 影响行数
* @return 操作结果
*/
@ -151,7 +151,7 @@ public class BaseController
/**
* 响应返回结果
*
*
* @param result 结果
* @return 操作结果
*/

View File

@ -3,11 +3,10 @@ package com.ruoyi.common.core.domain;
import java.util.HashMap;
import java.util.Objects;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.utils.StringUtils;
/**
* 操作消息提醒
*
*
* @author ruoyi
*/
public class AjaxResult extends HashMap<String, Object>
@ -32,7 +31,7 @@ public class AjaxResult extends HashMap<String, Object>
/**
* 初始化一个新创建的 AjaxResult 对象
*
*
* @param code 状态码
* @param msg 返回内容
*/
@ -44,7 +43,7 @@ public class AjaxResult extends HashMap<String, Object>
/**
* 初始化一个新创建的 AjaxResult 对象
*
*
* @param code 状态码
* @param msg 返回内容
* @param data 数据对象
@ -58,7 +57,7 @@ public class AjaxResult extends HashMap<String, Object>
/**
* 返回成功消息
*
*
* @return 成功消息
*/
public static AjaxResult success()
@ -68,7 +67,7 @@ public class AjaxResult extends HashMap<String, Object>
/**
* 返回成功数据
*
*
* @return 成功消息
*/
public static AjaxResult success(Object data)
@ -78,7 +77,7 @@ public class AjaxResult extends HashMap<String, Object>
/**
* 返回成功消息
*
*
* @param msg 返回内容
* @return 成功消息
*/
@ -89,7 +88,7 @@ public class AjaxResult extends HashMap<String, Object>
/**
* 返回成功消息
*
*
* @param msg 返回内容
* @param data 数据对象
* @return 成功消息
@ -124,18 +123,18 @@ public class AjaxResult extends HashMap<String, Object>
/**
* 返回错误消息
*
*
* @return 错误消息
*/
public static AjaxResult error()
{
return AjaxResult.error("操作失败");
return AjaxResult.error("操作失败", null);
}
/**
* 返回错误消息
*
* @param msg 返回内容
*
* @param msg 返回内容
* @return 错误消息
*/
public static AjaxResult error(String msg)
@ -145,7 +144,7 @@ public class AjaxResult extends HashMap<String, Object>
/**
* 返回错误消息
*
*
* @param msg 返回内容
* @param data 数据对象
* @return 错误消息
@ -157,16 +156,29 @@ public class AjaxResult extends HashMap<String, Object>
/**
* 返回错误消息
*
*
* @param code 状态码
* @param msg 返回内容
* @return 错误消息
*/
public static AjaxResult error(int code, String msg)
{
return new AjaxResult(code, msg, null);
public static AjaxResult error(int code, String msg) {
return error(code, msg, null);
}
/**
* 返回错误消息
*
* @param code 状态码
* @param msg 返回内容
* @param data
* @return 错误消息
*/
public static AjaxResult error(int code, String msg, Object data)
{
return new AjaxResult(code, msg, data);
}
/**
* 是否为成功消息
*

View File

@ -4,7 +4,7 @@ import com.ruoyi.common.enums.ServiceCode;
/**
* 业务异常
*
*
* @author ruoyi
*/
public final class ServiceException extends RuntimeException
@ -21,6 +21,19 @@ public final class ServiceException extends RuntimeException
*/
private String message;
/**
* 数据
*/
private Object data;
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
/**
* 错误明细内部调试错误
*
@ -46,6 +59,13 @@ public final class ServiceException extends RuntimeException
this.code = code;
}
public ServiceException(String message, Integer code, Object data) {
this.message = message;
this.code = code;
this.data = data;
}
public ServiceException(ServiceCode serviceCode) {
this.message = serviceCode.getMsg();
this.code = serviceCode.getCode();
@ -78,4 +98,4 @@ public final class ServiceException extends RuntimeException
this.detailMessage = detailMessage;
return this;
}
}
}

View File

@ -31,7 +31,7 @@ public abstract class RepeatSubmitInterceptor implements HandlerInterceptor
{
if (this.isRepeatSubmit(request, annotation))
{
AjaxResult ajaxResult = AjaxResult.error(annotation.message());
AjaxResult ajaxResult = AjaxResult.error(annotation.message(), null);
ServletUtils.renderString(response, JSON.toJSONString(ajaxResult));
return false;
}

View File

@ -10,7 +10,6 @@ import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingPathVariableException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.domain.AjaxResult;
@ -48,7 +47,7 @@ public class GlobalExceptionHandler
{
String requestURI = request.getRequestURI();
log.error("请求地址'{}',不支持'{}'请求", requestURI, e.getMethod());
return AjaxResult.error(e.getMessage());
return AjaxResult.error(e.getMessage(), null);
}
/**
@ -59,7 +58,7 @@ public class GlobalExceptionHandler
{
log.error(e.getMessage(), e);
Integer code = e.getCode();
return StringUtils.isNotNull(code) ? AjaxResult.error(code, e.getMessage()) : AjaxResult.error(e.getMessage());
return StringUtils.isNotNull(code) ? AjaxResult.error(code, e.getMessage(), e.getData()) : AjaxResult.error(e.getMessage(), e.getData());
}
/**
@ -68,7 +67,7 @@ public class GlobalExceptionHandler
@ExceptionHandler(NullPointerException.class)
public AjaxResult handleNullPointerException(NullPointerException e, HttpServletRequest request) {
log.error("发生空指针异常", e);
return AjaxResult.error("空指针异常");
return AjaxResult.error("空指针异常", null);
}
/**
@ -79,7 +78,7 @@ public class GlobalExceptionHandler
{
String requestURI = request.getRequestURI();
log.error("请求路径中缺少必需的路径变量'{}',发生系统异常.", requestURI, e);
return AjaxResult.error(String.format("请求路径中缺少必需的路径变量[%s]", e.getVariableName()));
return AjaxResult.error(String.format("请求路径中缺少必需的路径变量[%s]", e.getVariableName()), null);
}
/**
@ -90,7 +89,7 @@ public class GlobalExceptionHandler
{
String requestURI = request.getRequestURI();
log.error("请求参数类型不匹配'{}',发生系统异常.", requestURI, e);
return AjaxResult.error(String.format("请求参数类型不匹配,参数[%s]要求类型为:'%s',但输入值为:'%s'", e.getName(), e.getRequiredType().getName(), e.getValue()));
return AjaxResult.error(String.format("请求参数类型不匹配,参数[%s]要求类型为:'%s',但输入值为:'%s'", e.getName(), e.getRequiredType().getName(), e.getValue()), null);
}
/**
@ -101,7 +100,7 @@ public class GlobalExceptionHandler
{
String requestURI = request.getRequestURI();
log.error("请求地址'{}',发生未知异常.", requestURI, e);
return AjaxResult.error(e.getMessage());
return AjaxResult.error(e.getMessage(), null);
}
/**
@ -112,7 +111,7 @@ public class GlobalExceptionHandler
{
String requestURI = request.getRequestURI();
log.error("请求地址'{}',发生系统异常.", requestURI, e);
return AjaxResult.error(e.getMessage());
return AjaxResult.error(e.getMessage(), null);
}
/**
@ -123,7 +122,7 @@ public class GlobalExceptionHandler
{
log.error(e.getMessage(), e);
String message = e.getAllErrors().get(0).getDefaultMessage();
return AjaxResult.error(message);
return AjaxResult.error(message, null);
}
/**
@ -134,7 +133,7 @@ public class GlobalExceptionHandler
{
log.error(e.getMessage(), e);
String message = e.getBindingResult().getFieldError().getDefaultMessage();
return AjaxResult.error(message);
return AjaxResult.error(message, null);
}
/**
@ -143,6 +142,6 @@ public class GlobalExceptionHandler
@ExceptionHandler(DemoModeException.class)
public AjaxResult handleDemoModeException(DemoModeException e)
{
return AjaxResult.error("演示模式,不允许操作");
return AjaxResult.error("演示模式,不允许操作", null);
}
}

View File

@ -12,10 +12,7 @@ import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.*;
/**
* @author wjh
@ -40,13 +37,7 @@ public class IotConverterImpl implements IotConverter {
mac = data2.getTitle();
}
if (CollectionUtils.isNotEmptyElement(ds1)) {
return this.toIotDeviceInfo(ds1, ds2, mac);
} else if (CollectionUtils.isNotEmptyElement(ds2)) {
return this.toIotDeviceInfo(ds2, ds1, mac);
}
return null;
return this.toIotDeviceInfo(ds1, ds2, mac);
}
private IotDeviceInfo toIotDeviceInfo(List<CurrentDatastream> ds1, List<CurrentDatastream> ds2, String mac) {
@ -57,17 +48,20 @@ public class IotConverterImpl implements IotConverter {
IotDeviceInfo device = IotDeviceInfo.newDefaultInstance();
device.setMac(mac);
for (CurrentDatastream stream : ds1) {
// 将两个列表混合为一个列表按照时间正序排序
List<CurrentDatastream> list = new ArrayList<>();
if (CollectionUtils.isNotEmptyElement(ds1)) {
list.addAll(ds1);
}
if (CollectionUtils.isNotEmptyElement(ds2)) {
list.addAll(ds2);
}
list.sort(Comparator.comparing(CurrentDatastream::getAt));
for (CurrentDatastream stream : list) {
String id = stream.getId(); // 数据点ID
String value = stream.getValue().toString(); // 数据点取值取最新的值
Date at = stream.getAt();
if (ds2 != null) {
CurrentDatastream stream2 = ds2.stream().filter(item -> Objects.equals(item.getId(), stream.getId())).findFirst().orElse(null);
if (stream2 != null && stream2.getAt().getTime() > stream.getAt().getTime()) {
value = stream2.getValue().toString();
at = stream2.getAt();
}
}
switch (id) {
case ReceiveConstants.DS_V:

View File

@ -245,5 +245,6 @@ public class Device extends BaseEntity
@Excel(name = "设备版本号")
@ApiModelProperty("设备版本号")
@JsonView(JsonViewProfile.App.class)
private String version;
}

View File

@ -52,52 +52,7 @@ public class Risk extends BaseEntity
@ApiModelProperty("需要提交的材料类型列表")
private List<String> submitType;
@Excel(name = "实名认证ID")
@ApiModelProperty("实名认证ID")
private Long realNameId;
@Excel(name = "身份证正面")
@ApiModelProperty("身份证正面")
private String idCardFront;
@Excel(name = "身份证反面")
@ApiModelProperty("身份证反面")
private String idCardBack;
@Excel(name = "手持身份证照片")
@ApiModelProperty("手持身份证照片")
private String idCardHand;
@Excel(name = "使用场景视频")
@ApiModelProperty("使用场景视频")
private String video;
@Excel(name = "视频自定义词汇")
@ApiModelProperty("视频自定义词汇")
private String videoWords;
@Excel(name = "营业执照")
@ApiModelProperty("营业执照")
private String businessLicence;
@Excel(name = "审核人ID")
@ApiModelProperty("审核人ID")
private Long verifyId;
@Excel(name = "审核人名称")
@ApiModelProperty("审核人名称")
private String verifyBy;
@Excel(name = "审核意见")
@ApiModelProperty("审核意见")
private String verifyRemark;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "审核时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty("审核时间")
private LocalDateTime verifyTime;
@Excel(name = "审核状态", readConverterExp = "1=待审核,2=已通过,3=未通过")
@ApiModelProperty("审核状态")
private String verifyStatus;
}

View File

@ -21,20 +21,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
sr.reason,
sr.end_time,
sr.create_time,
sr.real_name_id,
sr.unseal_self,
sr.submit_type,
sr.id_card_front,
sr.id_card_back,
sr.id_card_hand,
sr.video,
sr.video_words,
sr.business_licence,
sr.verify_id,
sr.verify_by,
sr.verify_remark,
sr.verify_time,
sr.verify_status,
<include refid="isFinished"/> as is_finished,
if(su.is_real, su.real_name, su.user_name) as user_name
from ss_risk sr
@ -52,13 +41,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="query.userName != null and query.userName != ''">
and if(su.is_real, su.real_name, su.user_name) like concat('%', #{query.userName}, '%')
</if>
<if test="query.realNameId != null "> and sr.real_name_id = #{query.realNameId}</if>
<if test="query.unsealSelf != null "> and unseal_self = #{query.unsealSelf}</if>
<if test="query.videoWords != null and query.videoWords != ''"> and video_words like concat('%', #{query.videoWords}, '%')</if>
<if test="query.verifyId != null "> and verify_id = #{query.verifyId}</if>
<if test="query.verifyBy != null and query.verifyBy != ''"> and verify_by like concat('%', #{query.verifyBy}, '%')</if>
<if test="query.verifyRemark != null and query.verifyRemark != ''"> and verify_remark like concat('%', #{query.verifyRemark}, '%')</if>
<if test="query.verifyStatus != null and query.verifyStatus != ''"> and verify_status = #{query.verifyStatus}</if>
<if test="query.isFinished != null">
<if test="query.isFinished">and <include refid="isFinished"/></if>
<if test="!query.isFinished">and !<include refid="isFinished"/></if>
@ -85,20 +69,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="reason != null">reason,</if>
<if test="endTime != null">end_time,</if>
<if test="createTime != null">create_time,</if>
<if test="realNameId != null">real_name_id,</if>
<if test="unsealSelf != null">unseal_self,</if>
<if test="submitType != null">submit_type,</if>
<if test="idCardFront != null">id_card_front,</if>
<if test="idCardBack != null">id_card_back,</if>
<if test="idCardHand != null">id_card_hand,</if>
<if test="video != null">video,</if>
<if test="videoWords != null">video_words,</if>
<if test="businessLicence != null">business_licence,</if>
<if test="verifyId != null">verify_id,</if>
<if test="verifyBy != null">verify_by,</if>
<if test="verifyRemark != null">verify_remark,</if>
<if test="verifyTime != null">verify_time,</if>
<if test="verifyStatus != null">verify_status,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="userId != null">#{userId},</if>
@ -106,20 +79,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="reason != null">#{reason},</if>
<if test="endTime != null">#{endTime},</if>
<if test="createTime != null">#{createTime},</if>
<if test="realNameId != null">#{realNameId},</if>
<if test="unsealSelf != null">#{unsealSelf},</if>
<if test="submitType != null">#{submitType,typeHandler=com.ruoyi.system.mapper.typehandler.StringSplitListTypeHandler},</if>
<if test="idCardFront != null">#{idCardFront},</if>
<if test="idCardBack != null">#{idCardBack},</if>
<if test="idCardHand != null">#{idCardHand},</if>
<if test="video != null">#{video},</if>
<if test="videoWords != null">#{videoWords},</if>
<if test="businessLicence != null">#{businessLicence},</if>
<if test="verifyId != null">#{verifyId},</if>
<if test="verifyBy != null">#{verifyBy},</if>
<if test="verifyRemark != null">#{verifyRemark},</if>
<if test="verifyTime != null">#{verifyTime},</if>
<if test="verifyStatus != null">#{verifyStatus},</if>
</trim>
</insert>
@ -146,20 +108,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="data.reason != null">reason = #{data.reason},</if>
<if test="data.endTime != null">end_time = #{data.endTime},</if>
<if test="data.createTime != null">create_time = #{data.createTime},</if>
<if test="data.realNameId != null">real_name_id = #{data.realNameId},</if>
<if test="data.unsealSelf != null">unseal_self = #{data.unsealSelf},</if>
<if test="data.submitType != null">submit_type = #{data.submitType,typeHandler=com.ruoyi.system.mapper.typehandler.StringSplitListTypeHandler},</if>
<if test="data.idCardFront != null">id_card_front = #{data.idCardFront},</if>
<if test="data.idCardBack != null">id_card_back = #{data.idCardBack},</if>
<if test="data.idCardHand != null">id_card_hand = #{data.idCardHand},</if>
<if test="data.video != null">video = #{data.video},</if>
<if test="data.videoWords != null">video_words = #{data.videoWords},</if>
<if test="data.businessLicence != null">business_licence = #{data.businessLicence},</if>
<if test="data.verifyId != null">verify_id = #{data.verifyId},</if>
<if test="data.verifyBy != null">verify_by = #{data.verifyBy},</if>
<if test="data.verifyRemark != null">verify_remark = #{data.verifyRemark},</if>
<if test="data.verifyTime != null">verify_time = #{data.verifyTime},</if>
<if test="data.verifyStatus != null">verify_status = #{data.verifyStatus},</if>
</sql>
<delete id="deleteRiskByRiskId" parameterType="Long">

View File

@ -0,0 +1,11 @@
package com.ruoyi.ss.risk.service;
import com.ruoyi.ss.risk.domain.Risk;
/**
* @author wjh
* 2024/11/25
*/
public interface RiskConverter {
}

View File

@ -78,8 +78,4 @@ public interface RiskService
*/
int limitWithdraw(Long userId, String reason);
/**
* 修改风控实名认证ID
*/
int updateRealNameId(Long riskId, Long realNameId);
}

View File

@ -11,4 +11,16 @@ public interface RiskValidator {
* 判断风控是否属于当前用户
*/
boolean isUser(RiskVO risk, Long userId);
/**
* 判断风控是否属于当前用户
*/
boolean isUser(Long riskId, Long userId);
/**
* 判断风控是否存在
* @param riskId
*/
boolean isExist(Long riskId);
}

View File

@ -0,0 +1,14 @@
package com.ruoyi.ss.risk.service.impl;
import com.ruoyi.ss.risk.service.RiskConverter;
import org.springframework.stereotype.Service;
/**
* @author wjh
* 2024/11/25
*/
@Service
public class RiskConverterImpl implements RiskConverter {
}

View File

@ -123,15 +123,4 @@ public class RiskServiceImpl implements RiskService
risk.setUnsealSelf(true);
return this.insertRisk(risk);
}
@Override
public int updateRealNameId(Long riskId, Long realNameId) {
if (riskId == null || realNameId == null) {
return 0;
}
Risk data = new Risk();
data.setRiskId(riskId);
data.setRealNameId(realNameId);
return this.updateRisk(data);
}
}

View File

@ -1,7 +1,9 @@
package com.ruoyi.ss.risk.service.impl;
import com.ruoyi.ss.risk.domain.RiskVO;
import com.ruoyi.ss.risk.service.RiskService;
import com.ruoyi.ss.risk.service.RiskValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Objects;
@ -14,8 +16,29 @@ import static com.ruoyi.common.utils.SecurityUtils.getUserId;
*/
@Service
public class RiskValidatorImpl implements RiskValidator {
@Autowired
private RiskService riskService;
@Override
public boolean isUser(RiskVO risk, Long userId) {
return risk != null && userId != null && Objects.equals(risk.getUserId(), getUserId());
}
@Override
public boolean isUser(Long riskId, Long userId) {
if (riskId == null || userId == null) {
return false;
}
RiskVO risk = riskService.selectRiskByRiskId(riskId);
return isUser(risk, userId);
}
@Override
public boolean isExist(Long riskId) {
if (riskId == null) {
return false;
}
return riskService.selectRiskByRiskId(riskId) != null;
}
}

View File

@ -0,0 +1,88 @@
package com.ruoyi.ss.riskInfo.domain;
import java.time.LocalDateTime;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.core.domain.ValidGroup;
import io.swagger.annotations.ApiModelProperty;
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;
import javax.validation.constraints.NotNull;
/**
* 风控材料对象 ss_risk_info
*
* @author ruoyi
* @date 2024-11-25
*/
@Data
public class RiskInfo extends BaseEntity
{
private static final long serialVersionUID = 1L;
private Long infoId;
@Excel(name = "风控ID")
@ApiModelProperty("风控ID")
@NotNull(message = "风控ID不允许为空", groups = ValidGroup.FrontCreate.class)
private Long riskId;
@Excel(name = "状态", readConverterExp = "1=未提交,2=待审核,3=已通过,4=未通过")
@ApiModelProperty("状态")
private String status;
@Excel(name = "实名认证ID")
@ApiModelProperty("实名认证ID")
private Long realNameId;
@Excel(name = "身份证正面")
@ApiModelProperty("身份证正面")
private String idCardFront;
@Excel(name = "身份证反面")
@ApiModelProperty("身份证反面")
private String idCardBack;
@Excel(name = "手持身份证照片")
@ApiModelProperty("手持身份证照片")
private String idCardHand;
@Excel(name = "使用场景视频")
@ApiModelProperty("使用场景视频")
private String video;
@Excel(name = "责任视频")
@ApiModelProperty("责任视频")
private String dutyVideo;
@Excel(name = "营业执照")
@ApiModelProperty("营业执照")
private String businessLicence;
@Excel(name = "审核人ID")
@ApiModelProperty("审核人ID")
private Long verifyId;
@Excel(name = "审核人名称")
@ApiModelProperty("审核人名称")
private String verifyBy;
@Excel(name = "审核意见")
@ApiModelProperty("审核意见")
private String verifyRemark;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "审核时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty("审核时间")
private LocalDateTime verifyTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "提交时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty("提交时间")
private LocalDateTime submitTime;
}

View File

@ -0,0 +1,11 @@
package com.ruoyi.ss.riskInfo.domain;
import lombok.Data;
/**
* @author wjh
* 2024/11/25
*/
@Data
public class RiskInfoQuery extends RiskInfoVO {
}

View File

@ -0,0 +1,26 @@
package com.ruoyi.ss.riskInfo.domain;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* @author wjh
* 2024/11/25
*/
@Data
public class RiskInfoVO extends RiskInfo {
@ApiModelProperty("用户ID")
private Long userId;
@ApiModelProperty("用户名称")
private String userName;
@ApiModelProperty("风控提交材料列表")
private List<String> riskSubmitType;
@ApiModelProperty("风控是否结束")
private Boolean riskIsFinished;
}

View File

@ -0,0 +1,20 @@
package com.ruoyi.ss.riskInfo.domain.dto;
import com.ruoyi.ss.riskInfo.domain.RiskInfoVO;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* @author wjh
* 2024/11/25
*/
@Data
public class RiskInfoSubmitDTO extends RiskInfoVO {
@ApiModelProperty("是否提交")
@NotNull(message = "是否提交不允许为空")
private Boolean isSubmit;
}

View File

@ -0,0 +1,23 @@
package com.ruoyi.ss.riskInfo.domain.enums;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
/**
* @author wjh
* 2024/11/25
*/
@Getter
@AllArgsConstructor
public enum RiskInfoStatus {
WAIT_SUBMIT("1", "未提交"),
WAIT_VERIFY("2", "待审核"),
PASS("3", "已通过"),
REJECT("4", "未通过");
private final String status;
private final String desc;
}

View File

@ -0,0 +1,64 @@
package com.ruoyi.ss.riskInfo.mapper;
import java.util.List;
import com.ruoyi.ss.riskInfo.domain.RiskInfo;
import com.ruoyi.ss.riskInfo.domain.RiskInfoVO;
import com.ruoyi.ss.riskInfo.domain.RiskInfoQuery;
import org.apache.ibatis.annotations.Param;
/**
* 风控材料Mapper接口
*
* @author ruoyi
* @date 2024-11-25
*/
public interface RiskInfoMapper
{
/**
* 查询风控材料
*
* @param infoId 风控材料主键
* @return 风控材料
*/
public RiskInfoVO selectRiskInfoByInfoId(Long infoId);
/**
* 查询风控材料列表
*
* @param query 风控材料
* @return 风控材料集合
*/
public List<RiskInfoVO> selectRiskInfoList(@Param("query")RiskInfoQuery query);
/**
* 新增风控材料
*
* @param riskInfo 风控材料
* @return 结果
*/
public int insertRiskInfo(RiskInfo riskInfo);
/**
* 修改风控材料
*
* @param riskInfo 风控材料
* @return 结果
*/
public int updateRiskInfo(@Param("data") RiskInfo riskInfo);
/**
* 删除风控材料
*
* @param infoId 风控材料主键
* @return 结果
*/
public int deleteRiskInfoByInfoId(Long infoId);
/**
* 批量删除风控材料
*
* @param infoIds 需要删除的数据主键集合
* @return 结果
*/
public int deleteRiskInfoByInfoIds(Long[] infoIds);
}

View File

@ -0,0 +1,141 @@
<?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.riskInfo.mapper.RiskInfoMapper">
<resultMap type="RiskInfoVO" id="RiskInfoResult" autoMapping="true">
<result property="riskSubmitType" column="risk_submit_type" typeHandler="com.ruoyi.system.mapper.typehandler.StringSplitListTypeHandler"/>
</resultMap>
<sql id="selectRiskInfoVo">
select
sri.info_id,
sri.risk_id,
sri.status,
sri.real_name_id,
sri.id_card_front,
sri.id_card_back,
sri.id_card_hand,
sri.video,
sri.duty_video,
sri.video_words,
sri.business_licence,
sri.verify_id,
sri.verify_by,
sri.verify_remark,
sri.verify_time,
sri.create_time,
sri.submit_time,
sr.user_id as user_id,
sr.submit_type as risk_submit_type,
<include refid="com.ruoyi.ss.risk.mapper.RiskMapper.isFinished"/> as risk_is_finished,
if(su.is_real, su.real_name, su.user_name) as user_name
from ss_risk_info sri
left join ss_risk sr on sr.risk_id = sri.risk_id
left join sm_user su on su.user_id = sr.user_id
</sql>
<sql id="searchCondition">
<if test="query.infoId != null "> and sri.info_id = #{query.infoId}</if>
<if test="query.riskId != null "> and sri.risk_id = #{query.riskId}</if>
<if test="query.status != null and query.status != ''"> and sri.status = #{query.status}</if>
<if test="query.realNameId != null "> and sri.real_name_id = #{query.realNameId}</if>
<if test="query.videoWords != null and query.videoWords != ''"> and sri.video_words like concat('%', #{query.videoWords}, '%')</if>
<if test="query.verifyId != null "> and sri.verify_id = #{query.verifyId}</if>
<if test="query.verifyBy != null and query.verifyBy != ''"> and sri.verify_by like concat('%', #{query.verifyBy}, '%')</if>
<if test="query.verifyRemark != null and query.verifyRemark != ''"> and sri.verify_remark like concat('%', #{query.verifyRemark}, '%')</if>
<if test="query.userId != null "> and sr.user_id = #{query.userId}</if>
<if test="query.userName != null and query.userName != ''"> and if(su.is_real, su.real_name, su.user_name) like concat('%', #{query.userName}, '%')</if>
</sql>
<select id="selectRiskInfoList" parameterType="RiskInfoQuery" resultMap="RiskInfoResult">
<include refid="selectRiskInfoVo"/>
<where>
<include refid="searchCondition"/>
</where>
</select>
<select id="selectRiskInfoByInfoId" parameterType="Long" resultMap="RiskInfoResult">
<include refid="selectRiskInfoVo"/>
where sri.info_id = #{infoId}
</select>
<insert id="insertRiskInfo" parameterType="RiskInfo" useGeneratedKeys="true" keyProperty="infoId">
insert into ss_risk_info
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="riskId != null">risk_id,</if>
<if test="status != null and status != ''">`status`,</if>
<if test="realNameId != null">real_name_id,</if>
<if test="idCardFront != null">id_card_front,</if>
<if test="idCardBack != null">id_card_back,</if>
<if test="idCardHand != null">id_card_hand,</if>
<if test="video != null">video,</if>
<if test="dutyVideo != null">duty_video,</if>
<if test="videoWords != null">video_words,</if>
<if test="businessLicence != null">business_licence,</if>
<if test="verifyId != null">verify_id,</if>
<if test="verifyBy != null">verify_by,</if>
<if test="verifyRemark != null">verify_remark,</if>
<if test="verifyTime != null">verify_time,</if>
<if test="createTime != null">create_time,</if>
<if test="submitTime != null">submit_time,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="riskId != null">#{riskId},</if>
<if test="status != null and status != ''">#{status},</if>
<if test="realNameId != null">#{realNameId},</if>
<if test="idCardFront != null">#{idCardFront},</if>
<if test="idCardBack != null">#{idCardBack},</if>
<if test="idCardHand != null">#{idCardHand},</if>
<if test="video != null">#{video},</if>
<if test="dutyVideo != null">#{dutyVideo},</if>
<if test="videoWords != null">#{videoWords},</if>
<if test="businessLicence != null">#{businessLicence},</if>
<if test="verifyId != null">#{verifyId},</if>
<if test="verifyBy != null">#{verifyBy},</if>
<if test="verifyRemark != null">#{verifyRemark},</if>
<if test="verifyTime != null">#{verifyTime},</if>
<if test="createTime != null">#{createTime},</if>
<if test="submitTime != null">#{submitTime},</if>
</trim>
</insert>
<update id="updateRiskInfo" parameterType="RiskInfo">
update ss_risk_info
<trim prefix="SET" suffixOverrides=",">
<include refid="updateColumns"/>
</trim>
where info_id = #{data.infoId}
</update>
<sql id="updateColumns">
<if test="data.riskId != null">risk_id = #{data.riskId},</if>
<if test="data.status != null and data.status != ''">`status` = #{data.status},</if>
<if test="data.realNameId != null">real_name_id = #{data.realNameId},</if>
<if test="data.idCardFront != null">id_card_front = #{data.idCardFront},</if>
<if test="data.idCardBack != null">id_card_back = #{data.idCardBack},</if>
<if test="data.idCardHand != null">id_card_hand = #{data.idCardHand},</if>
<if test="data.video != null">video = #{data.video},</if>
<if test="data.dutyVideo != null">duty_video = #{data.dutyVideo},</if>
<if test="data.videoWords != null">video_words = #{data.videoWords},</if>
<if test="data.businessLicence != null">business_licence = #{data.businessLicence},</if>
<if test="data.verifyId != null">verify_id = #{data.verifyId},</if>
<if test="data.verifyBy != null">verify_by = #{data.verifyBy},</if>
<if test="data.verifyRemark != null">verify_remark = #{data.verifyRemark},</if>
<if test="data.verifyTime != null">verify_time = #{data.verifyTime},</if>
<if test="data.createTime != null">create_time = #{data.createTime},</if>
<if test="data.submitTime != null">submit_time = #{data.submitTime},</if>
</sql>
<delete id="deleteRiskInfoByInfoId" parameterType="Long">
delete from ss_risk_info where info_id = #{infoId}
</delete>
<delete id="deleteRiskInfoByInfoIds" parameterType="String">
delete from ss_risk_info where info_id in
<foreach item="infoId" collection="array" open="(" separator="," close=")">
#{infoId}
</foreach>
</delete>
</mapper>

View File

@ -0,0 +1,21 @@
package com.ruoyi.ss.riskInfo.service;
import com.ruoyi.ss.riskInfo.domain.RiskInfo;
import com.ruoyi.ss.riskInfo.domain.dto.RiskInfoSubmitDTO;
/**
* @author wjh
* 2024/11/25
*/
public interface RiskInfoConverter {
/**
* 当app新增时转为po
*/
RiskInfo toPoByAppCreate(RiskInfoSubmitDTO dto);
/**
* 当app修改时转为po
*/
RiskInfo toPoByAppUpdate(RiskInfoSubmitDTO dto);
}

View File

@ -0,0 +1,76 @@
package com.ruoyi.ss.riskInfo.service;
import java.util.List;
import com.ruoyi.ss.riskInfo.domain.RiskInfo;
import com.ruoyi.ss.riskInfo.domain.RiskInfoVO;
import com.ruoyi.ss.riskInfo.domain.RiskInfoQuery;
/**
* 风控材料Service接口
*
* @author ruoyi
* @date 2024-11-25
*/
public interface RiskInfoService
{
/**
* 查询风控材料
*
* @param infoId 风控材料主键
* @return 风控材料
*/
public RiskInfoVO selectRiskInfoByInfoId(Long infoId);
/**
* 查询风控材料列表
*
* @param riskInfo 风控材料
* @return 风控材料集合
*/
public List<RiskInfoVO> selectRiskInfoList(RiskInfoQuery riskInfo);
/**
* 新增风控材料
*
* @param riskInfo 风控材料
* @return 结果
*/
public int insertRiskInfo(RiskInfo riskInfo);
/**
* 修改风控材料
*
* @param riskInfo 风控材料
* @return 结果
*/
public int updateRiskInfo(RiskInfo riskInfo);
/**
* 批量删除风控材料
*
* @param infoIds 需要删除的风控材料主键集合
* @return 结果
*/
public int deleteRiskInfoByInfoIds(Long[] infoIds);
/**
* 删除风控材料信息
*
* @param infoId 风控材料主键
* @return 结果
*/
public int deleteRiskInfoByInfoId(Long infoId);
/**
* 提交
*/
int submit(Long infoId);
/**
*
* @param infoId
* @param realNameId
* @return
*/
int updateRealName(Long infoId, Long realNameId);
}

View File

@ -0,0 +1,26 @@
package com.ruoyi.ss.riskInfo.service;
import com.ruoyi.ss.riskInfo.domain.RiskInfo;
import com.ruoyi.ss.riskInfo.domain.RiskInfoVO;
/**
* @author wjh
* 2024/11/25
*/
public interface RiskInfoValidator {
boolean isUser(Long infoId, Long userId);
boolean isUser(RiskInfoVO info, Long userId);
/**
* 前校验
*/
void preCheck(RiskInfo riskInfo);
/**
* 提交前校验
*/
void preSubmitCheck(RiskInfoVO data);
}

View File

@ -0,0 +1,49 @@
package com.ruoyi.ss.riskInfo.service.impl;
import com.ruoyi.ss.riskInfo.domain.RiskInfo;
import com.ruoyi.ss.riskInfo.domain.dto.RiskInfoSubmitDTO;
import com.ruoyi.ss.riskInfo.domain.enums.RiskInfoStatus;
import com.ruoyi.ss.riskInfo.service.RiskInfoConverter;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
/**
* @author wjh
* 2024/11/25
*/
@Service
public class RiskInfoConverterImpl implements RiskInfoConverter {
@Override
public RiskInfo toPoByAppCreate(RiskInfoSubmitDTO dto) {
if (dto == null) {
return null;
}
RiskInfo po = new RiskInfo();
po.setStatus(RiskInfoStatus.WAIT_SUBMIT.getStatus());
po.setRiskId(dto.getRiskId());
po.setIdCardFront(dto.getIdCardFront());
po.setIdCardBack(dto.getIdCardBack());
po.setIdCardHand(dto.getIdCardHand());
po.setVideo(dto.getVideo());
po.setDutyVideo(dto.getDutyVideo());
po.setBusinessLicence(dto.getBusinessLicence());
return po;
}
@Override
public RiskInfo toPoByAppUpdate(RiskInfoSubmitDTO dto) {
if (dto == null) {
return null;
}
RiskInfo po = new RiskInfo();
po.setInfoId(dto.getInfoId());
po.setIdCardFront(dto.getIdCardFront());
po.setIdCardBack(dto.getIdCardBack());
po.setIdCardHand(dto.getIdCardHand());
po.setVideo(dto.getVideo());
po.setDutyVideo(dto.getDutyVideo());
po.setBusinessLicence(dto.getBusinessLicence());
return po;
}
}

View File

@ -0,0 +1,133 @@
package com.ruoyi.ss.riskInfo.service.impl;
import java.time.LocalDateTime;
import java.util.List;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.ss.riskInfo.domain.enums.RiskInfoStatus;
import com.ruoyi.ss.riskInfo.service.RiskInfoValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.ss.riskInfo.mapper.RiskInfoMapper;
import com.ruoyi.ss.riskInfo.domain.RiskInfo;
import com.ruoyi.ss.riskInfo.domain.RiskInfoVO;
import com.ruoyi.ss.riskInfo.domain.RiskInfoQuery;
import com.ruoyi.ss.riskInfo.service.RiskInfoService;
/**
* 风控材料Service业务层处理
*
* @author ruoyi
* @date 2024-11-25
*/
@Service
public class RiskInfoServiceImpl implements RiskInfoService
{
@Autowired
private RiskInfoMapper riskInfoMapper;
@Autowired
private RiskInfoValidator riskInfoValidator;
/**
* 查询风控材料
*
* @param infoId 风控材料主键
* @return 风控材料
*/
@Override
public RiskInfoVO selectRiskInfoByInfoId(Long infoId)
{
return riskInfoMapper.selectRiskInfoByInfoId(infoId);
}
/**
* 查询风控材料列表
*
* @param riskInfo 风控材料
* @return 风控材料
*/
@Override
public List<RiskInfoVO> selectRiskInfoList(RiskInfoQuery riskInfo)
{
return riskInfoMapper.selectRiskInfoList(riskInfo);
}
/**
* 新增风控材料
*
* @param riskInfo 风控材料
* @return 结果
*/
@Override
public int insertRiskInfo(RiskInfo riskInfo) {
// 校验
riskInfoValidator.preCheck(riskInfo);
riskInfo.setCreateTime(DateUtils.getNowDate());
return riskInfoMapper.insertRiskInfo(riskInfo);
}
/**
* 修改风控材料
*
* @param riskInfo 风控材料
* @return 结果
*/
@Override
public int updateRiskInfo(RiskInfo riskInfo) {
// 校验
riskInfoValidator.preCheck(riskInfo);
return riskInfoMapper.updateRiskInfo(riskInfo);
}
/**
* 批量删除风控材料
*
* @param infoIds 需要删除的风控材料主键
* @return 结果
*/
@Override
public int deleteRiskInfoByInfoIds(Long[] infoIds)
{
return riskInfoMapper.deleteRiskInfoByInfoIds(infoIds);
}
/**
* 删除风控材料信息
*
* @param infoId 风控材料主键
* @return 结果
*/
@Override
public int deleteRiskInfoByInfoId(Long infoId)
{
return riskInfoMapper.deleteRiskInfoByInfoId(infoId);
}
@Override
public int submit(Long infoId) {
if (infoId == null) {
return 0;
}
// 校验数据
RiskInfoVO info = this.selectRiskInfoByInfoId(infoId);
riskInfoValidator.preSubmitCheck(info);
RiskInfoVO data = new RiskInfoVO();
data.setInfoId(infoId);
data.setSubmitTime(LocalDateTime.now());
data.setStatus(RiskInfoStatus.WAIT_VERIFY.getStatus());
return riskInfoMapper.updateRiskInfo(data);
}
@Override
public int updateRealName(Long infoId, Long realNameId) {
if (infoId == null || realNameId == null) {
return 0;
}
RiskInfo data = new RiskInfo();
data.setInfoId(infoId);
data.setRealNameId(realNameId);
return this.updateRiskInfo(data);
}
}

View File

@ -0,0 +1,88 @@
package com.ruoyi.ss.riskInfo.service.impl;
import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.collection.CollectionUtils;
import com.ruoyi.ss.realName.domain.RealNameVO;
import com.ruoyi.ss.realName.service.RealNameService;
import com.ruoyi.ss.risk.domain.enums.RiskSubmitType;
import com.ruoyi.ss.risk.service.RiskValidator;
import com.ruoyi.ss.riskInfo.domain.RiskInfo;
import com.ruoyi.ss.riskInfo.domain.RiskInfoVO;
import com.ruoyi.ss.riskInfo.service.RiskInfoService;
import com.ruoyi.ss.riskInfo.service.RiskInfoValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Objects;
/**
* @author wjh
* 2024/11/25
*/
@Service
public class RiskInfoValidatorImpl implements RiskInfoValidator {
@Autowired
private RiskInfoService riskInfoService;
@Autowired
private RiskValidator riskValidator;
@Autowired
private RealNameService realNameService;
@Override
public boolean isUser(Long infoId, Long userId) {
if (userId == null || infoId == null) {
return false;
}
RiskInfoVO info = riskInfoService.selectRiskInfoByInfoId(infoId);
return isUser(info, userId);
}
@Override
public boolean isUser(RiskInfoVO info, Long userId) {
return info != null && userId != null && Objects.equals(userId, info.getUserId());
}
@Override
public void preCheck(RiskInfo data) {
ServiceUtil.assertion(data == null, "参数错误");
// 校验风控是否存在
if (data.getRiskId() != null) {
boolean exist = riskValidator.isExist(data.getRiskId());
ServiceUtil.assertion(!exist, "风控信息不存在");
}
}
@Override
public void preSubmitCheck(RiskInfoVO data) {
ServiceUtil.assertion(data == null, "参数错误");
if (CollectionUtils.isEmptyElement(data.getRiskSubmitType())) {
return;
}
List<String> types = data.getRiskSubmitType();
if (types.contains(RiskSubmitType.REAL_NAME.getCode())) {
RealNameVO realName = realNameService.selectRealNameById(data.getRealNameId());
ServiceUtil.assertion(realName == null, "请提交正确的实名认证信息");
}
if (types.contains(RiskSubmitType.ID_CARD.getCode())) {
ServiceUtil.assertion(StringUtils.isAnyBlank(data.getIdCardFront(), data.getIdCardBack()), "请填写完整的身份证信息");
}
if (types.contains(RiskSubmitType.ID_CARD_HAND.getCode())) {
ServiceUtil.assertion(StringUtils.isAnyBlank(data.getIdCardHand()), "请上传手持身份证照片");
}
if (types.contains(RiskSubmitType.VIDEO.getCode())) {
ServiceUtil.assertion(StringUtils.isAnyBlank(data.getVideo()), "请上传使用场景视频");
}
if (types.contains(RiskSubmitType.BUSINESS_LICENCE.getCode())) {
ServiceUtil.assertion(StringUtils.isAnyBlank(data.getBusinessLicence()), "请上传营业执照");
}
}
}

View File

@ -347,15 +347,12 @@ public class TransactionBillValidatorImpl extends BaseValidator implements Trans
if (CollectionUtils.isNotEmptyElement(riskList)) {
RiskVO risk = riskList.get(0);
ServiceUtil.assertion(risk == null, "风控信息异常");
if (risk.getUnsealSelf() != null && !risk.getUnsealSelf()) {
throw new ServiceException("您被限制退款,且不允许自行解封:" + risk.getReason());
}
LocalDateTime endTime = risk.getEndTime();
if (endTime == null) {
throw new ServiceException("您被限制退款:" + risk.getReason(), ServiceCode.RISK_REFUND.getCode());
throw new ServiceException("您被限制退款:" + risk.getReason(), ServiceCode.RISK_REFUND.getCode(), risk.getRiskId());
} else if (endTime.isAfter(LocalDateTime.now())){
throw new ServiceException("您被限制退款至" + DateUtils.format(endTime, DateUtils.YYYY_MM_DD_HH_MM_SS) + ":" + risk.getReason(), ServiceCode.RISK_REFUND.getCode());
throw new ServiceException("您被限制退款至" + DateUtils.format(endTime, DateUtils.YYYY_MM_DD_HH_MM_SS) + ":" + risk.getReason(), ServiceCode.RISK_REFUND.getCode(), risk.getRiskId());
}
}
}

View File

@ -96,14 +96,17 @@ public class WithdrawValidatorImpl extends BaseValidator implements WithdrawVali
if (CollectionUtils.isNotEmptyElement(riskList)) {
RiskVO risk = riskList.get(0);
ServiceUtil.assertion(risk == null, "风控信息异常");
if (risk.getUnsealSelf() != null && !risk.getUnsealSelf()) {
throw new ServiceException("您被限制提现,且不允许自行解封:" + risk.getReason());
}
LocalDateTime endTime = risk.getEndTime();
if (endTime == null) {
throw new ServiceException("您被限制提现:" + risk.getReason(), ServiceCode.RISK_WITHDRAW.getCode());
throw new ServiceException("您被限制提现:" + risk.getReason(),
ServiceCode.RISK_WITHDRAW.getCode(),
risk.getRiskId()
);
} else if (endTime.isAfter(LocalDateTime.now())){
throw new ServiceException("您被限制提现至" + DateUtils.format(endTime, DateUtils.YYYY_MM_DD_HH_MM_SS) + ":" + risk.getReason(), ServiceCode.RISK_WITHDRAW.getCode());
throw new ServiceException("您被限制提现至" + DateUtils.format(endTime, DateUtils.YYYY_MM_DD_HH_MM_SS) + ":" + risk.getReason(),
ServiceCode.RISK_WITHDRAW.getCode(),
risk.getRiskId()
);
}
}
}

View File

@ -18,6 +18,6 @@ public class UserFaceDTO {
private String mobile;
// 风控ID
private Long riskId;
private Long riskInfoId;
}

View File

@ -39,7 +39,7 @@ public class UserRealNameDTO {
@Pattern(regexp = RegexpUtils.MOBILE_PHONE_REGEXP, message = "手机号格式错误")
private String realPhone;
@ApiModelProperty("风控ID")
private Long riskId;
@ApiModelProperty("风控信息ID")
private Long riskInfoId;
}

View File

@ -3,7 +3,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.recordBalance.domain.enums.RecordBalanceBstType;
import com.ruoyi.ss.risk.domain.RiskVO;
import com.ruoyi.ss.riskInfo.domain.RiskInfoVO;
import com.ruoyi.ss.user.domain.SmUserQuery;
import com.ruoyi.ss.user.domain.SmUserVO;
import com.ruoyi.ss.user.domain.dto.UserRealNameDTO;
@ -225,10 +225,11 @@ public interface ISmUserService
/**
* 刷新实名认证结果
*
* @param userId 用户ID
* @return 认证结果是否成功
*/
int refreshRealName(Long userId);
String refreshRealName(Long userId);
/**
* 根据用户ID列表查询
@ -256,7 +257,7 @@ public interface ISmUserService
/**
* 风控实名认证
*
* @param risk @return
* @param info @return
*/
UserRealNameVO riskRealName(RiskVO risk);
UserRealNameVO riskRealName(RiskInfoVO info);
}

View File

@ -35,6 +35,8 @@ import com.ruoyi.ss.recordBalance.service.RecordBalanceService;
import com.ruoyi.ss.risk.domain.RiskVO;
import com.ruoyi.ss.risk.domain.enums.RiskSubmitType;
import com.ruoyi.ss.risk.service.RiskService;
import com.ruoyi.ss.riskInfo.domain.RiskInfoVO;
import com.ruoyi.ss.riskInfo.service.RiskInfoService;
import com.ruoyi.ss.store.domain.StoreQuery;
import com.ruoyi.ss.store.domain.StoreVo;
import com.ruoyi.ss.store.service.StoreService;
@ -104,6 +106,9 @@ public class SmUserServiceImpl implements ISmUserService
@Autowired
private UserValidator userValidator;
@Autowired
private RiskInfoService riskInfoService;
// 活体检测返回地址
public static final String LIVENESS_RETURN_URL = SpringUtils.getRequiredProperty("liveness.returnUrl");
@ -383,7 +388,7 @@ public class SmUserServiceImpl implements ISmUserService
faceDto.setMobile(dto.getRealPhone());
faceDto.setIdCard(dto.getRealIdCard());
faceDto.setType(dto.getType());
faceDto.setRiskId(dto.getRiskId());
faceDto.setRiskInfoId(dto.getRiskInfoId());
redisCache.setCacheObject(cacheKey, faceDto, 10, TimeUnit.MINUTES);
// 返回数据
@ -408,9 +413,9 @@ public class SmUserServiceImpl implements ISmUserService
}
@Override
public int refreshRealName(Long userId) {
public String refreshRealName(Long userId) {
if (userId == null) {
return 0;
return null;
}
// 通过userId获取用户提交的信息
@ -449,11 +454,15 @@ public class SmUserServiceImpl implements ISmUserService
realName.setType(face.getType());
// 普通实名
if (RealNameType.NORMAL.getType().equals(face.getType())) {
return this.handleNormalRealName(realName, cacheKey);
int result = this.handleNormalRealName(realName, cacheKey);
ServiceUtil.assertion(result != 1, "实名认证失败");
return RealNameType.NORMAL.getType(); // 普通实名
}
// 风控实名修改用户风控信息
else {
return this.handleRiskRealName(realName, cacheKey, face.getRiskId());
int result = this.handleRiskRealName(realName, cacheKey, face.getRiskInfoId());
ServiceUtil.assertion(result != 1, "风控实名失败");
return RealNameType.RISK.getType(); // 风控实名
}
}
@ -462,10 +471,10 @@ public class SmUserServiceImpl implements ISmUserService
* @param realName 实名认证
* @param cacheKey 缓存key
*/
private int handleRiskRealName(RealName realName, String cacheKey, Long riskId) {
private int handleRiskRealName(RealName realName, String cacheKey, Long riskInfoId) {
// 查询用户是否有风控信息
RiskVO risk = riskService.selectRiskByRiskId(riskId);
ServiceUtil.assertion(risk == null, "风控信息不存在");
RiskInfoVO info = riskInfoService.selectRiskInfoByInfoId(riskInfoId);
ServiceUtil.assertion(info == null, "风控材料信息不存在");
Integer result = transactionTemplate.execute(status -> {
// 插入实名认证信息
@ -473,8 +482,7 @@ public class SmUserServiceImpl implements ISmUserService
ServiceUtil.assertion(insert != 1, "新增实名认证失败");
// 修改实名认证ID
int update = riskService.updateRealNameId(riskId, realName.getId());
ServiceUtil.assertion(update != 1, "修改风控信息失败");
riskInfoService.updateRealName(riskInfoId, realName.getId());
// 删除缓存
redisCache.deleteObject(cacheKey);
@ -482,7 +490,12 @@ public class SmUserServiceImpl implements ISmUserService
return insert;
});
return result == null ? 0 : result;
// 提交
if (result != null && result == 1) {
return riskInfoService.submit(riskInfoId);
}
return 0;
}
/**
@ -582,19 +595,19 @@ public class SmUserServiceImpl implements ISmUserService
}
@Override
public UserRealNameVO riskRealName(RiskVO risk) {
public UserRealNameVO riskRealName(RiskInfoVO info) {
UserRealNameDTO dto = new UserRealNameDTO();
dto.setType(RealNameType.RISK.getType());
ServiceUtil.assertion(risk == null, "风控信息不存在");
ServiceUtil.assertion(risk.getIsFinished() != null && risk.getIsFinished(), "当前风控已结束,无需实名认证");
ServiceUtil.assertion(CollectionUtils.isEmpty(risk.getSubmitType())
|| !risk.getSubmitType().contains(RiskSubmitType.REAL_NAME.getCode()),
ServiceUtil.assertion(info == null, "风控信息不存在");
ServiceUtil.assertion(info.getRiskIsFinished() != null && info.getRiskIsFinished(), "当前风控已结束,无需实名认证");
ServiceUtil.assertion(CollectionUtils.isEmpty(info.getRiskSubmitType())
|| !info.getRiskSubmitType().contains(RiskSubmitType.REAL_NAME.getCode()),
"当前风控无需提交实名认证"
);
dto.setRiskId(risk.getRiskId());
dto.setRiskInfoId(info.getInfoId());
SmUserVO user = this.selectSmUserByUserId(risk.getUserId());
SmUserVO user = this.selectSmUserByUserId(info.getUserId());
if (user.getIsReal()) {
if (user.getRealName() != null) {
dto.setRealName(user.getRealName());

View File

@ -0,0 +1,37 @@
package com.ruoyi.web.controller.app;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.ss.risk.domain.Risk;
import com.ruoyi.ss.risk.domain.RiskVO;
import com.ruoyi.ss.risk.service.RiskService;
import com.ruoyi.ss.risk.service.RiskValidator;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* @author wjh
* 2024/11/25
*/
@RestController
@RequestMapping("/app/risk")
public class AppRiskController extends BaseController {
@Autowired
private RiskService riskService;
@Autowired
private RiskValidator riskValidator;
@ApiOperation("获取风控信息详情")
@GetMapping("/{riskId}")
public AjaxResult getInfo(@PathVariable Long riskId) {
RiskVO risk = riskService.selectRiskByRiskId(riskId);
if (!riskValidator.isUser(risk, getUserId())) {
return error("您无权查看该风控信息");
}
return success(risk);
}
}

View File

@ -0,0 +1,103 @@
package com.ruoyi.web.controller.app;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.ValidGroup;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.ss.risk.service.RiskValidator;
import com.ruoyi.ss.riskInfo.domain.RiskInfo;
import com.ruoyi.ss.riskInfo.domain.RiskInfoQuery;
import com.ruoyi.ss.riskInfo.domain.RiskInfoVO;
import com.ruoyi.ss.riskInfo.domain.dto.RiskInfoSubmitDTO;
import com.ruoyi.ss.riskInfo.domain.enums.RiskInfoStatus;
import com.ruoyi.ss.riskInfo.service.RiskInfoConverter;
import com.ruoyi.ss.riskInfo.service.RiskInfoService;
import com.ruoyi.ss.riskInfo.service.RiskInfoValidator;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
/**
* @author wjh
* 2024/11/25
*/
@RestController
@RequestMapping("/app/riskInfo")
public class AppRiskInfoController extends BaseController {
@Autowired
private RiskInfoService riskInfoService;
@Autowired
private RiskInfoConverter riskInfoConverter;
@Autowired
private RiskValidator riskValidator;
@Autowired
private RiskInfoValidator riskInfoValidator;
@ApiOperation("新增风控材料")
@PostMapping
public AjaxResult save(@RequestBody @Validated(ValidGroup.FrontCreate.class) RiskInfoSubmitDTO dto) {
if (!riskValidator.isUser(dto.getRiskId(), getUserId())) {
return error("您无权提交该风控信息");
}
RiskInfo po = riskInfoConverter.toPoByAppCreate(dto);
int insert = riskInfoService.insertRiskInfo(po);
ServiceUtil.assertion(insert != 1, "数据保存失败");
if (dto.getIsSubmit() != null && dto.getIsSubmit()) {
int submit = riskInfoService.submit(po.getInfoId());
ServiceUtil.assertion(submit != 1, "数据提交失败");
}
return success(po.getInfoId());
}
@ApiOperation("修改风控材料")
@PutMapping
public AjaxResult update(@RequestBody @Validated(ValidGroup.FrontUpdate.class) RiskInfoSubmitDTO dto) {
if (!riskInfoValidator.isUser(dto.getInfoId(), getUserId())) {
return error("您无权修改该风控材料");
}
if (!riskValidator.isUser(dto.getRiskId(), getUserId())) {
return error("您无权修改该风控信息");
}
RiskInfo po = riskInfoConverter.toPoByAppUpdate(dto);
int update = riskInfoService.updateRiskInfo(po);
ServiceUtil.assertion(update != 1, "数据保存失败");
if (dto.getIsSubmit() != null && dto.getIsSubmit()) {
int submit = riskInfoService.submit(po.getInfoId());
ServiceUtil.assertion(submit != 1, "数据提交失败");
}
return success(po.getInfoId());
}
@ApiOperation("查询风控材料详情")
@GetMapping("/{infoId}")
public AjaxResult getDetail(@PathVariable Long infoId) {
RiskInfoVO riskInfo = riskInfoService.selectRiskInfoByInfoId(infoId);
if (!riskValidator.isUser(riskInfo.getRiskId(), getUserId())) {
return error("您无权查看该风控信息");
}
return success(riskInfo);
}
@ApiOperation("查询本人风控材料列表")
@GetMapping("/list")
public TableDataInfo getList(RiskInfoQuery query) {
startPage();
query.setUserId(getUserId());
return getDataTable(riskInfoService.selectRiskInfoList(query));
}
}

View File

@ -17,6 +17,9 @@ import com.ruoyi.ss.realName.domain.enums.RealNameType;
import com.ruoyi.ss.risk.domain.RiskVO;
import com.ruoyi.ss.risk.service.RiskService;
import com.ruoyi.ss.risk.service.RiskValidator;
import com.ruoyi.ss.riskInfo.domain.RiskInfoVO;
import com.ruoyi.ss.riskInfo.service.RiskInfoService;
import com.ruoyi.ss.riskInfo.service.RiskInfoValidator;
import com.ruoyi.ss.user.domain.SmUserQuery;
import com.ruoyi.ss.user.domain.SmUserVO;
import com.ruoyi.ss.user.domain.dto.UserChangeMobileDTO;
@ -72,6 +75,12 @@ public class AppUserController extends BaseController {
@Autowired
private RiskValidator riskValidator;
@Autowired
private RiskInfoService riskInfoService;
@Autowired
private RiskInfoValidator riskInfoValidator;
@ApiOperation("获取当前登录前台用户的信息")
@GetMapping("/userInfo")
@JsonView(JsonViewProfile.AppMch.class)
@ -122,16 +131,16 @@ public class AppUserController extends BaseController {
@ApiOperation("用户风控实名认证")
@PutMapping("/riskRealName")
public AjaxResult riskRealName(@RequestParam Long riskId) {
RiskVO risk = riskService.selectRiskByRiskId(riskId);
ServiceUtil.assertion(!riskValidator.isUser(risk, getUserId()), "风控信息不存在");
return success(userService.riskRealName(risk));
public AjaxResult riskRealName(@RequestParam Long riskInfoId) {
RiskInfoVO info = riskInfoService.selectRiskInfoByInfoId(riskInfoId);
ServiceUtil.assertion(!riskInfoValidator.isUser(info, getUserId()), "风控信息不存在");
return success(userService.riskRealName(info));
}
@ApiOperation("刷新用户实名认证结果")
@GetMapping("/refreshRealName")
public AjaxResult refreshRealName() {
return toAjax(userService.refreshRealName(getUserId()));
return AjaxResult.success("操作成功", userService.refreshRealName(getUserId()));
}
@ApiOperation("标记用户已读商户协议")

View File

@ -22,7 +22,7 @@ import com.ruoyi.system.service.ISysConfigService;
/**
* 验证码操作处理
*
*
* @author ruoyi
*/
@RestController
@ -36,7 +36,7 @@ public class CaptchaController
@Autowired
private RedisCache redisCache;
@Autowired
private ISysConfigService configService;
/**
@ -84,7 +84,7 @@ public class CaptchaController
}
catch (IOException e)
{
return AjaxResult.error(e.getMessage());
return AjaxResult.error(e.getMessage(), null);
}
ajax.put("uuid", uuid);

View File

@ -7,10 +7,7 @@ import javax.servlet.http.HttpServletResponse;
import cn.binarywang.wx.miniapp.api.WxMaService;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.core.domain.ValidGroup;
import com.ruoyi.common.utils.qiniu.QiNiuUtils;
import com.ruoyi.system.domain.bo.VerificationCodeDTO;
import com.ruoyi.system.domain.enums.verificationCode.CodeBusinessType;
import com.ruoyi.system.service.IVerificationCodeService;
import io.swagger.annotations.ApiOperation;
import me.chanjar.weixin.common.bean.WxJsapiSignature;
@ -19,7 +16,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.config.RuoYiConfig;
@ -108,7 +104,7 @@ public class CommonController
}
catch (Exception e)
{
return AjaxResult.error(e.getMessage());
return AjaxResult.error(e.getMessage(), null);
}
}
@ -145,7 +141,7 @@ public class CommonController
}
catch (Exception e)
{
return AjaxResult.error(e.getMessage());
return AjaxResult.error(e.getMessage(), null);
}
}

View File

@ -0,0 +1,107 @@
package com.ruoyi.web.controller.ss;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
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.riskInfo.domain.RiskInfo;
import com.ruoyi.ss.riskInfo.domain.RiskInfoVO;
import com.ruoyi.ss.riskInfo.domain.RiskInfoQuery;
import com.ruoyi.ss.riskInfo.service.RiskInfoService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
/**
* 风控材料Controller
*
* @author ruoyi
* @date 2024-11-25
*/
@RestController
@RequestMapping("/ss/riskInfo")
public class RiskInfoController extends BaseController
{
@Autowired
private RiskInfoService riskInfoService;
/**
* 查询风控材料列表
*/
@PreAuthorize("@ss.hasPermi('ss:riskInfo:list')")
@GetMapping("/list")
public TableDataInfo list(RiskInfoQuery query)
{
startPage();
startOrderBy();
List<RiskInfoVO> list = riskInfoService.selectRiskInfoList(query);
return getDataTable(list);
}
/**
* 导出风控材料列表
*/
@PreAuthorize("@ss.hasPermi('ss:riskInfo:export')")
@Log(title = "风控材料", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, RiskInfoQuery query)
{
List<RiskInfoVO> list = riskInfoService.selectRiskInfoList(query);
ExcelUtil<RiskInfoVO> util = new ExcelUtil<RiskInfoVO>(RiskInfoVO.class);
util.exportExcel(response, list, "风控材料数据");
}
/**
* 获取风控材料详细信息
*/
@PreAuthorize("@ss.hasPermi('ss:riskInfo:query')")
@GetMapping(value = "/{infoId}")
public AjaxResult getInfo(@PathVariable("infoId") Long infoId)
{
return success(riskInfoService.selectRiskInfoByInfoId(infoId));
}
/**
* 新增风控材料
*/
@PreAuthorize("@ss.hasPermi('ss:riskInfo:add')")
@Log(title = "风控材料", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody RiskInfo riskInfo)
{
return toAjax(riskInfoService.insertRiskInfo(riskInfo));
}
/**
* 修改风控材料
*/
@PreAuthorize("@ss.hasPermi('ss:riskInfo:edit')")
@Log(title = "风控材料", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody RiskInfo riskInfo)
{
return toAjax(riskInfoService.updateRiskInfo(riskInfo));
}
/**
* 删除风控材料
*/
@PreAuthorize("@ss.hasPermi('ss:riskInfo:remove')")
@Log(title = "风控材料", businessType = BusinessType.DELETE)
@DeleteMapping("/{infoIds}")
public AjaxResult remove(@PathVariable Long[] infoIds)
{
return toAjax(riskInfoService.deleteRiskInfoByInfoIds(infoIds));
}
}

View File

@ -134,4 +134,8 @@ tm:
# 活体检测跳转地址
liveness:
returnUrl: http://192.168.2.12:3001/liveness
returnUrl: http://192.168.2.40:3001/liveness
ali:
appId: 2021004193649611
privateSecret: 123