Merge remote-tracking branch 'origin/master' into debug

# Conflicts:
#	smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/core/domain/entity/SmUser.java
#	smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/service/impl/TransactionBillServiceImpl.java
#	smart-switch-service/src/main/java/com/ruoyi/ss/user/mapper/SmUserMapper.xml
#	smart-switch-service/src/main/java/com/ruoyi/ss/user/service/ISmUserService.java
This commit is contained in:
墨大叔 2024-09-23 09:56:01 +08:00
commit 4554d18f7b
22 changed files with 328 additions and 79 deletions

View File

@ -68,7 +68,7 @@ public class IotConstants {
public static final String COMMAND_RECHARGE = "time";
/**
* 命令 设置断电方式
* 命令 设置断电方式
*/
public static final String COMMAND_OUTAGE_WAY = "set";

View File

@ -1,6 +1,7 @@
package com.ruoyi.common.core.domain.entity;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonView;
@ -192,4 +193,13 @@ public class SmUser extends BaseEntity
@JsonView(JsonViewProfile.App.class)
private Boolean readMchLicence;
@Excel(name = "风险提现次数")
@ApiModelProperty("风险提现次数")
private Integer riskCount;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "限制提现时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty("限制提现时间")
private LocalDateTime limitWithdrawTime;
}

View File

@ -22,7 +22,8 @@ public enum RedisLockKey {
ADD_TIME_BILL("add_time_bill", "创建时长订单"),
PAY_BILL("pay_bill", "支付订单"),
PREPAY_DEPOSIT("prepay_deposit", "支付押金"),
ADD_RECHARGE_ORDER("add_recharge_order", "创建充值订单");
ADD_RECHARGE_ORDER("add_recharge_order", "创建充值订单"),
PAY_BILL_SUCCESS("pay_bill_success", "支付订单成功处理");
private final String key;

View File

@ -5,6 +5,7 @@ import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.Temporal;
import java.util.Calendar;
import java.util.Date;
import org.apache.commons.lang3.time.DateFormatUtils;
@ -316,4 +317,12 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
public static LocalDateTime toLocalDate(String timeStr, String format) {
return LocalDateTime.parse(timeStr, DateTimeFormatter.ofPattern(format));
}
public static LocalDateTime toLocalDateTime(Date date) {
return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
}
public static String format(LocalDateTime time, String format) {
return time.format(DateTimeFormatter.ofPattern(format));
}
}

View File

@ -85,7 +85,7 @@ public class HttpUtils
{
result.append(line);
}
log.debug("recv - {}", result);
// log.debug("recv - {}", result);
}
catch (ConnectException e)
{
@ -153,7 +153,7 @@ public class HttpUtils
{
result.append(line);
}
log.debug("recv - {}", result);
// log.debug("recv - {}", result);
}
catch (ConnectException e)
{
@ -224,7 +224,7 @@ public class HttpUtils
result.append(new String(ret.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8));
}
}
log.debug("recv - {}", result);
// log.debug("recv - {}", result);
conn.disconnect();
br.close();
}
@ -329,7 +329,7 @@ public class HttpUtils
{
result.append(line);
}
log.debug("recv - {}", result);
// log.debug("recv - {}", result);
}
catch (ConnectException e)
{
@ -396,7 +396,7 @@ public class HttpUtils
{
result.append(line);
}
log.debug("recv - {}", result);
// log.debug("recv - {}", result);
}
catch (ConnectException e)
{

View File

@ -21,7 +21,10 @@ public enum ConfigKey {
DAILY_WITHDRAW_COUNT("daily.withdraw.count", "单日单用户提现次数(次)"),
NOVERIFY_WITHDRAW_SINGLE("noverify.withdraw.single", "提现单笔免审核额度(元)"),
RECHARGE_MIN_SERVICE("recharge.min.service","充值最低服务费(元)"),
ORDER_AUTO_CLOSE_CD("order.auto.close.cd", "订单自动关闭冷却时间(分)");
ORDER_AUTO_CLOSE_CD("order.auto.close.cd", "订单自动关闭冷却时间(分)"),
RISK_WITHDRAW_TIME("risk.withdraw.time", "风控订单和提现相隔时长(分钟)"),
RISK_WITHDRAW_COUNT("risk.withdraw.count", "累计风险次数"),
RISK_WITHDRAW_ENABLED("risk.withdraw.enabled", "是否开启提现风控");
private final String key;
private final String msg;

View File

@ -105,10 +105,10 @@ public class IotServiceImpl implements IotService {
String sendUrl = iotHost + IotConstants.ADDS_HISTORY_DATAPOINTS + "?"+param;
String token = Token.getToken();
log.info("IOT获取到Authorization:【{}】",token);
// log.info("IOT获取到Authorization:【{}】",token);
String result = HttpUtils.sendGetWithToken(sendUrl, null, token);
log.info("IOT返回的结果【{}】",result);
// log.info("IOT返回的结果【{}】",result);
if (!StringUtils.hasText(result)) {
log.error("与OneNet通信异常");
return null;
@ -159,7 +159,7 @@ public class IotServiceImpl implements IotService {
String param = "device_name=" + deviceName + "&product_id=" + productId;
String token = Token.getToken();
log.info("IOT获取到Authorization:【{}】",token);
// log.info("IOT获取到Authorization:【{}】",token);
String result = HttpUtils.sendGetWithToken(sendUrl, param, token);
if (!StringUtils.hasText(result)) {

View File

@ -14,8 +14,8 @@ import java.util.Objects;
@Getter
public enum DeviceOutageWay {
NOT_OUTAGE("0", "到时不断电"),
IMMEDIATE("1", "到时立即断电");
NOT_OUTAGE("0", ""),
IMMEDIATE("1", "");
private final String value;
private final String msg;

View File

@ -579,23 +579,23 @@ public class DeviceServiceImpl implements DeviceService
this.pullDeviceInfoAsync(Collections.singletonList(deviceId), 3, TimeUnit.SECONDS);
// 时长结束后修改设备状态
scheduledExecutorService.schedule(()-> {
freshStatus(deviceId);
}, seconds, TimeUnit.SECONDS);
// scheduledExecutorService.schedule(()-> {
// freshStatus(deviceId);
// }, seconds, TimeUnit.SECONDS);
}
return success;
}
private void freshStatus(Long deviceId) {
DeviceVO device = deviceMapper.selectSmDeviceByDeviceId(deviceId);
freshStatus(device);
}
// private void freshStatus(Long deviceId) {
// DeviceVO device = deviceMapper.selectSmDeviceByDeviceId(deviceId);
// freshStatus(device);
// }
@Override
public void freshStatus(DeviceVO device) {
if (device == null) {
if (device == null || device.getExpireTime() == null) {
return;
}
if (!DeviceStatus.USING.getStatus().equals(device.getStatus())) {
@ -610,12 +610,12 @@ public class DeviceServiceImpl implements DeviceService
return;
}
// 如果没有过期则延迟至过期时间继续查询
if (between.getSeconds() > 0) {
scheduledExecutorService.schedule(() -> {
freshStatus(device.getDeviceId());
}, between.getSeconds() , TimeUnit.SECONDS);
}
// // 如果没有过期则延迟至过期时间继续查询
// if (between.getSeconds() > 0) {
// scheduledExecutorService.schedule(() -> {
// freshStatus(device.getDeviceId());
// }, between.getSeconds() , TimeUnit.SECONDS);
// }
}
/**
@ -632,7 +632,7 @@ public class DeviceServiceImpl implements DeviceService
for (DeviceVO device : list) {
if (StringUtils.hasText(device.getMac())) {
String status = iotService.getOnlineStatus(device.getMac(), device.getModelProductId()).getStatus();
log.info("device: {} {} online status is {}", device.getDeviceId(), device.getMac(), status);
// log.info("device: {} {} online status is {}", device.getDeviceId(), device.getMac(), status);
device.setOnlineStatus(status);
} else {
device.setOnlineStatus(DeviceOnlineStatus.OFFLINE.getStatus());
@ -752,9 +752,9 @@ public class DeviceServiceImpl implements DeviceService
// 判断设备是否正在使用
// 设备过期时间 > 当前时间则正在使用
boolean hasTime = device.getExpireTime().isAfter(now);
boolean hasTime = device.getExpireTime() != null && device.getExpireTime().isAfter(now);
// 若当前设备有电量则正在使用
boolean hasEle = data.getSurplusEle().compareTo(BigDecimal.ZERO) > 0;
boolean hasEle = data.getSurplusEle() != null && data.getSurplusEle().compareTo(BigDecimal.ZERO) > 0;
// 若开关开启则正在使用
boolean hasOpen = DevicePowerStatus.ON.getStatus().equals(data.getPowerStatus());
if (hasTime || hasEle || hasOpen) {

View File

@ -277,35 +277,41 @@ public class PayBillServiceImpl implements PayBillService
private void handleSuccess(PayBillVO payBill, LocalDateTime payTime) {
ServiceUtil.assertion(payBill == null, "支付订单不存在");
log.info("获取支付订单:{}", payBill.getPayNo());
// 若已经支付成功则跳过
if (PayBillStatus.payedList().contains(payBill.getStatus())) {
return;
}
ServiceUtil.assertion(!PayBillStatus.PAYING.getStatus().equals(payBill.getStatus()), "该支付订单不是正在支付的支付订单");
Long lockKey = payBill.getPayId();
transactionTemplate.execute(status -> {
// 修改支付订单状态
PayBill data = new PayBill();
data.setStatus(PayBillStatus.PAY_SUCCESS.getStatus());
data.setPayTime(payTime);
PayBillQuery query = new PayBillQuery();
query.setStatus(PayBillStatus.PAYING.getStatus());
query.setPayId(payBill.getPayId());
int update = this.updateByQuery(data, query);
ServiceUtil.assertion(update != 1, "支付订单状态已改变,请稍后再试");
// 处理业务
PayBillBstType bstType = PayBillBstType.parse(payBill.getBstType());
if (bstType != null && bstType.getAfterPay() != null) {
PayBillVO newPayBill = selectPayBillByPayId(payBill.getPayId());
AfterPay afterPay = SpringUtils.getBean(bstType.getAfterPay());
int bstResult = afterPay.onPaySuccess(newPayBill);
ServiceUtil.assertion(bstResult == 0, "业务处理失败");
ServiceUtil.assertion(redisLock.lock(RedisLockKey.PAY_BILL_SUCCESS, lockKey), "支付订单正在处理中:payId=" + payBill.getPayId());
try {
// 若已经支付成功则跳过
if (PayBillStatus.payedList().contains(payBill.getStatus())) {
return;
}
ServiceUtil.assertion(!PayBillStatus.PAYING.getStatus().equals(payBill.getStatus()), "该支付订单不是正在支付的支付订单");
return update;
});
transactionTemplate.execute(status -> {
// 修改支付订单状态
PayBill data = new PayBill();
data.setStatus(PayBillStatus.PAY_SUCCESS.getStatus());
data.setPayTime(payTime);
PayBillQuery query = new PayBillQuery();
query.setStatus(PayBillStatus.PAYING.getStatus());
query.setPayId(payBill.getPayId());
int update = this.updateByQuery(data, query);
ServiceUtil.assertion(update != 1, "支付订单状态已改变,请稍后再试");
// 处理业务
PayBillBstType bstType = PayBillBstType.parse(payBill.getBstType());
if (bstType != null && bstType.getAfterPay() != null) {
PayBillVO newPayBill = selectPayBillByPayId(payBill.getPayId());
AfterPay afterPay = SpringUtils.getBean(bstType.getAfterPay());
int bstResult = afterPay.onPaySuccess(newPayBill);
ServiceUtil.assertion(bstResult == 0, "业务处理失败");
}
return update;
});
} finally {
redisLock.unlock(RedisLockKey.PAY_BILL_SUCCESS, lockKey);
}
}
@Override

View File

@ -41,6 +41,7 @@ public class RecordTimeConverterImpl implements RecordTimeConverter {
record.setDeviceId(device == null ? null : device.getDeviceId());
record.setAmount(seconds);
record.setReason(reason);
record.setType(type);
if (user != null) {
record.setOperatorId(user.getUserId());
record.setOperatorName(user.getUserName());

View File

@ -299,4 +299,9 @@ public interface TransactionBillService
* 开启/关闭订单设备
*/
int switchDevice(TransactionBillVO bill, boolean open);
/**
* 查询最后一个
*/
TransactionBillVO selectLastOne(TransactionBillQuery query);
}

View File

@ -0,0 +1,17 @@
package com.ruoyi.ss.transactionBill.service;
import com.ruoyi.common.core.domain.ValidateResult;
import com.ruoyi.ss.transactionBill.domain.bo.WithdrawBO;
/**
* @author wjh
* 2024/9/21
*/
public interface WithdrawValidator {
/**
* 判断提现是否有风险
*/
boolean hasRisk(WithdrawBO bo);
}

View File

@ -3,6 +3,7 @@ package com.ruoyi.ss.transactionBill.service.impl;
import com.github.pagehelper.PageHelper;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.domain.ValidateResult;
import com.ruoyi.common.core.redis.RedisLock;
import com.ruoyi.common.core.redis.enums.RedisLockKey;
import com.ruoyi.common.enums.BusinessStatus;
@ -52,6 +53,7 @@ import com.ruoyi.ss.transactionBill.mapper.TransactionBillMapper;
import com.ruoyi.ss.transactionBill.service.TransactionBillConverter;
import com.ruoyi.ss.transactionBill.service.TransactionBillService;
import com.ruoyi.ss.transactionBill.service.TransactionBillValidator;
import com.ruoyi.ss.transactionBill.service.WithdrawValidator;
import com.ruoyi.ss.transfer.domain.TransferVO;
import com.ruoyi.ss.transfer.interfaces.AfterTransfer;
import com.ruoyi.ss.transfer.service.TransferConverter;
@ -157,6 +159,9 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
@Autowired
private TransactionBillConverter transactionBillConverter;
@Autowired
private WithdrawValidator withdrawValidator;
/**
* 查询充值记录
*
@ -415,8 +420,36 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
AccountVO account = bo.getAccount();
ServiceUtil.assertion(user == null, "用户不存在");
ServiceUtil.assertion(user.getIsReal() == null || !user.getIsReal(), "用户未实名认证,无法提现", HttpStatus.NO_REAL_NAME);
ServiceUtil.assertion(user.getLimitWithdraw() != null && user.getLimitWithdraw(), "您被限制提现:" + user.getLimitWithdrawReason(), HttpStatus.LIMIT_WITHDRAW);
ServiceUtil.assertion(user.getIsReal() == null || !user.getIsReal(), "用户未实名认证,无法提现");
// 判断用户是否被限制提现
boolean limitWithdraw = user.getLimitWithdraw() != null && user.getLimitWithdraw();
if (limitWithdraw) {
LocalDateTime limitWithdrawTime = user.getLimitWithdrawTime();
if (limitWithdrawTime == null) {
throw new ServiceException("您被永久限制提现:" + user.getLimitWithdrawReason());
} else {
throw new ServiceException("您被限制提现至" + DateUtils.format(limitWithdrawTime, DateUtils.YYYY_MM_DD_HH_MM_SS) + ":" + user.getLimitWithdrawReason() );
}
}
// 风控规则判断用户是否有风险
boolean enabled = sysConfigService.getBoolean(ConfigKey.RISK_WITHDRAW_ENABLED);
if (enabled) {
boolean hasRisk = withdrawValidator.hasRisk(bo);
if (hasRisk) {
// 累计一次风险次数
userService.addRiskCount(userId, 1);
// 若用户风险次数已达到阈值将用户标记为提现风险
int riskWithdrawCount = sysConfigService.getInt(ConfigKey.RISK_WITHDRAW_COUNT);
if (user.getRiskCount() + 1 >= riskWithdrawCount) {
userService.limitWithdraw(userId, LocalDateTime.now().plusDays(1), "根据风控规则判断,您的提现具有风险", "风险客户");
// 返回错误
throw new ServiceException("提现具有风险,无法提现");
}
}
}
// 判断今天提现成功和正在审核中的提现是否超过限额
String dailyLimitStr = sysConfigService.selectConfigByKey(ConfigKey.DAILY_WITHDRAW_AMOUNT.getKey());
@ -725,13 +758,18 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
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()), "设备已充值成功,不允许再次充值");
if (TransactionBillDeviceRechargeStatus.SUCCESS.getStatus().equals(bill.getDeviceRechargeStatus())) {
log.warn( "设备已充值成功,不允许再次充值:billId={}", billId);
return false;
}
ServiceUtil.assertion(TransactionBillDeviceRechargeStatus.BLUETOOTH.getStatus().equals(bill.getDeviceRechargeStatus()), "设备已选择蓝牙充值,请使用蓝牙进行充值");
// 刷新设备数据
deviceService.pullDeviceInfo(bill.getDeviceId());
Boolean result = transactionTemplate.execute(status -> {
// 刷新设备数据
deviceService.pullDeviceInfo(bill.getDeviceId());
Boolean result = (Boolean) transactionTemplate.execute(status -> {
DeviceVO device = deviceService.selectSmDeviceByDeviceId(bill.getDeviceId());
// 如果设备离线则直接返回失败
@ -745,7 +783,7 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
// 修改设备充值状态成功
int updateRecharge = transactionBillMapper.updateDeviceRechargeStatus(bill.getBillId(), TransactionBillDeviceRechargeStatus.SUCCESS.getStatus());
ServiceUtil.assertion(updateRecharge != 1, "订单状态发生变化,请稍后重试");
ServiceUtil.assertion(updateRecharge != 1, "设备充值状态发生变化,请稍后重试");
try {
if (SuitFeeType.TIME.getType().equals(bill.getSuitFeeType())) {
@ -851,14 +889,33 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
return updateCount;
});
// 异步充值设备尝试3次
if (result != null && result == 1) {
// 设备充值
rechargeDevice(bill.getBillId());
this.tryRechargeDevice(bill.getBillId(), 3);
}
return result == null ? 0 : result;
}
/**
* 异步尝试充值设备
* @param billId
* @param tryCount
*/
private void tryRechargeDevice(Long billId, int tryCount) {
if (tryCount <= 0) {
return;
}
scheduledExecutorService.schedule(()-> {
try {
boolean result = rechargeDevice(billId);
ServiceUtil.assertion(!result, String.format("尝试充值设备失败:billId=%s:剩余次数:%s,", billId, tryCount - 1));
} catch (Exception e) {
this.tryRechargeDevice(billId, tryCount - 1);
}
}, 0, TimeUnit.SECONDS);
}
@Override
public DoPayVO payDeposit(RechargePayDepositBO bo) {
// 校验
@ -1433,7 +1490,7 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
if (SuitFeeType.TIME.getType().equals(bill.getSuitFeeType())) {
recordTimeService.insertRecordTime(recordTimeConverter.toRecordTime(device, bill.toSecondSuitTime(), reason, user, RecordTimeType.TIME.getType()));
} else if (SuitFeeType.COUNT.getType().equals(bill.getSuitFeeType())) {
recordTimeService.insertRecordTime(recordTimeConverter.toRecordTime(device, bill.toSecondSuitTime(), reason, user, RecordTimeType.ELE.getType()));
recordTimeService.insertRecordTime(recordTimeConverter.toRecordTime(device, bill.getSuitTime(), reason, user, RecordTimeType.ELE.getType()));
}
}, 1L, TimeUnit.SECONDS);
}
@ -1627,6 +1684,12 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
}
}
@Override
public TransactionBillVO selectLastOne(TransactionBillQuery query) {
PageHelper.orderBy("stb.bill_id desc");
return selectOne(query);
}
@Override
public UserWithdrawServiceVO getUserWithdrawService(Long userId, Long channelId) {
SmUserVo user = userService.selectSmUserByUserId(userId);

View File

@ -0,0 +1,74 @@
package com.ruoyi.ss.transactionBill.service.impl;
import com.ruoyi.common.core.domain.BaseValidator;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.ss.transactionBill.domain.TransactionBillQuery;
import com.ruoyi.ss.transactionBill.domain.bo.WithdrawBO;
import com.ruoyi.ss.transactionBill.domain.dto.WithdrawDTO;
import com.ruoyi.ss.transactionBill.domain.enums.TransactionBillStatus;
import com.ruoyi.ss.transactionBill.domain.enums.TransactionBillType;
import com.ruoyi.ss.transactionBill.domain.vo.TransactionBillVO;
import com.ruoyi.ss.transactionBill.service.TransactionBillService;
import com.ruoyi.ss.transactionBill.service.WithdrawValidator;
import com.ruoyi.ss.user.domain.SmUserVo;
import com.ruoyi.system.domain.enums.config.ConfigKey;
import com.ruoyi.system.service.ISysConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.Duration;
import java.time.LocalDateTime;
/**
* @author wjh
* 2024/9/21
*/
@Service
public class WithdrawValidatorImpl extends BaseValidator implements WithdrawValidator {
@Autowired
private TransactionBillService transactionBillService;
@Autowired
private ISysConfigService sysConfigService;
@Autowired
private RedisCache redisCache;
/**
* 判断提现是否有风险
*
* @param bo
*/
@Override
public boolean hasRisk(WithdrawBO bo) {
if (bo == null || bo.getUser() == null || bo.getDto() == null) {
return false;
}
SmUserVo user = bo.getUser();
WithdrawDTO dto = bo.getDto();
// 查询最近一次的订单
TransactionBillQuery query = new TransactionBillQuery();
query.setUserId(user.getUserId());
query.setType(TransactionBillType.RECHARGE.getType());
query.setStatus(TransactionBillStatus.SUCCESS.getStatus());
TransactionBillVO recharge = transactionBillService.selectLastOne(query);
if (recharge == null || recharge.getPayTime() == null) {
return false;
}
// 判断订单金额是否和提现一致订单时间与提现时间是否相差较近
// 金额一致
boolean equalsMoney = recharge.getArrivalAmount() != null && dto.getMoney() != null && recharge.getArrivalAmount().compareTo(dto.getMoney()) == 0;
// 提现时间相近
int riskWithdrawTime = sysConfigService.getInt(ConfigKey.RISK_WITHDRAW_TIME); // 最低允许相隔时长分钟
Duration between = Duration.between(DateUtils.toLocalDateTime(recharge.getPayTime()), LocalDateTime.now());
boolean timeLimit = between.toMinutes() < riskWithdrawTime;
if (equalsMoney && timeLimit) {
return true;
}
return false;
}
}

View File

@ -109,4 +109,12 @@ public interface SmUserMapper
* 查询用户余额
*/
BigDecimal selectSumOfBalance(SmUserQuery query);
/**
* 增加一次风险次数
* @param userId
* @param count
* @return
*/
int addRiskCount(@Param("userId") Long userId,@Param("count") int count);
}

View File

@ -50,6 +50,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
su.limit_refund,
su.limit_refund_reason,
su.read_mch_licence,
su.risk_count,
su.limit_withdraw_time,
(select sum(stb.money) from sm_transaction_bill stb where stb.user_id = su.user_id and stb.type = '1' and stb.status = '2') as recharge_amount,
(select sum(stb.arrival_amount) from sm_transaction_bill stb where stb.user_id = su.user_id and stb.type = '2' and stb.status = '14') as with_drawl_amount,
(select sum(stb.arrival_amount) from sm_transaction_bill stb where stb.mch_id = su.user_id and stb.type = '1' and stb.status = '2') as total_income
@ -172,6 +174,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="limitRefund != null">limit_refund,</if>
<if test="limitRefundReason != null">limit_refund_reason,</if>
<if test="readMchLicence != null">read_mch_licence,</if>
<if test="riskCount != null">risk_count,</if>
<if test="limitWithdrawTime != null">limit_withdraw_time,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="userName != null and userName != ''">#{userName},</if>
@ -210,9 +214,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="limitRefund != null">#{limitRefund},</if>
<if test="limitRefundReason != null">#{limitRefundReason},</if>
<if test="readMchLicence != null">#{readMchLicence},</if>
<if test="riskCount != null">#{riskCount},</if>
<if test="limitWithdrawTime != null">#{limitWithdrawTime},</if>
</trim>
</insert>
<update id="addRiskCount">
update sm_user
set risk_count = risk_count + 1
where user_id = #{userId} and del_flag = '0'
</update>
<update id="addBalance">
update sm_user
set balance = balance + #{amount}
@ -258,6 +270,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="limitRefund != null">limit_refund = #{limitRefund},</if>
<if test="limitRefundReason != null">limit_refund_reason = #{limitRefundReason},</if>
<if test="readMchLicence != null">read_mch_licence = #{readMchLicence},</if>
<if test="riskCount != null">risk_count = #{riskCount},</if>
<if test="limitWithdrawTime != null">limit_withdraw_time = #{limitWithdrawTime},</if>
</trim>
where user_id = #{userId}
</update>

View File

@ -9,6 +9,7 @@ import com.ruoyi.ss.user.domain.dto.UserRealNameDTO;
import com.ruoyi.ss.user.domain.vo.UserRealNameVO;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
/**
@ -215,4 +216,19 @@ public interface ISmUserService
* 标记已读商户协议
*/
int readMchLicence(Long userId);
/**
* 限制提现
* @param userId
* @param limitTime
* @param reason
* @param remark
* @return
*/
int limitWithdraw(Long userId, LocalDateTime limitTime, String reason, String remark);
/**
* 添加一次风险次数
*/
int addRiskCount(Long userId, int count);
}

View File

@ -34,6 +34,7 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@ -340,6 +341,25 @@ public class SmUserServiceImpl implements ISmUserService
return smUserMapper.updateSmUser(data);
}
@Override
public int limitWithdraw(Long userId, LocalDateTime limitTime, String reason, String remark) {
if (userId == null) {
return 0;
}
SmUser data = new SmUser();
data.setUserId(userId);
data.setLimitWithdraw(true);
data.setLimitWithdrawTime(limitTime);
data.setLimitWithdrawReason(reason);
data.setRemark(remark);
return smUserMapper.updateSmUser(data);
}
@Override
public int addRiskCount(Long userId, int count) {
return smUserMapper.addRiskCount(userId, count);
}
/**
* 逻辑删除前校验
* @param userIds

View File

@ -31,18 +31,18 @@ public class DeviceStatusTask implements ApplicationRunner {
*/
@Override
public void run(ApplicationArguments args) throws Exception {
log.info("项目启动,查询正在使用中的设备");
DeviceQuery query = new DeviceQuery();
query.setStatus(DeviceStatus.USING.getStatus());
List<DeviceVO> list = deviceService.selectSmDeviceList(query);
if (CollectionUtils.isEmptyElement(list)) {
log.info("没有正在使用中的设备");
return;
}
for (DeviceVO device : list) {
deviceService.freshStatus(device);
}
// log.info("项目启动,查询正在使用中的设备");
// DeviceQuery query = new DeviceQuery();
// query.setStatus(DeviceStatus.USING.getStatus());
// List<DeviceVO> list = deviceService.selectSmDeviceList(query);
// if (CollectionUtils.isEmptyElement(list)) {
// log.info("没有正在使用中的设备");
// return;
// }
//
// for (DeviceVO device : list) {
// deviceService.freshStatus(device);
// }
}
}

View File

@ -272,6 +272,7 @@ public class AppTransactionBillController extends BaseController
@ApiOperation("支付押金")
@PutMapping("/payDeposit")
public AjaxResult payDeposit(@RequestBody @Validated PayDepositDTO dto) {
dto.setChannelId(1L);
return success(transactionBillService.payDeposit(transactionBillConverter.toRechargePayDepositBO(dto)));
}
@ -344,6 +345,7 @@ public class AppTransactionBillController extends BaseController
@ApiOperation("支付订单")
@PutMapping("/pay")
public AjaxResult pay(@RequestBody BillPayDTO dto) {
dto.setChannelId(1L);
TransactionBillVO bill = transactionBillService.selectSmTransactionBillByBillNo(dto.getBillNo());
if (!transactionBillValidator.isUser(bill, getUserId())) {
return error("这不是您的订单,无法支付");

View File

@ -33,7 +33,7 @@ wx:
# 设备配置
device:
# 项目启动时抄表
startRecord: true
startRecord: false
spring:
# redis 配置