diff --git a/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/constant/IotConstants.java b/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/constant/IotConstants.java
index dbfd279f..1a2e51e5 100644
--- a/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/constant/IotConstants.java
+++ b/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/constant/IotConstants.java
@@ -86,6 +86,11 @@ public class IotConstants {
public static final String COMMAND_SET_PASS = "pass";
+ /**
+ * 命令 设置语音播报阈值(秒)
+ */
+ public static final String COMMAND_SET_VOICE = "dj_set";
+
/**----------------------------命令end----------------------------*/
}
diff --git a/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/tm/TmPayService.java b/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/tm/TmPayService.java
index 4e5d100f..c6772952 100644
--- a/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/tm/TmPayService.java
+++ b/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/tm/TmPayService.java
@@ -23,8 +23,6 @@ import java.util.Map;
@Service
public class TmPayService {
- private final static String SIGNKEY = "b4ixpiogfj5vu3tbkv23gj0dvo2j2ksz";
-
@Autowired
private TmPayConfig config;
@@ -147,7 +145,7 @@ public class TmPayService {
params.remove("sign");
// 按照请求时的签名逻辑,生成签名字符串
String paramsStr = TmPayUtil.getAsciiSort(params); // 按ASCII排序
- String generatedSign = TmPayUtil.getMD5Code(paramsStr + "&key=" + SIGNKEY).toUpperCase(); // 重新生成签名
+ String generatedSign = TmPayUtil.getMD5Code(paramsStr + "&key=" + config.getSignKey()).toUpperCase(); // 重新生成签名
System.out.println("新生成的签名-----------:"+generatedSign);
// 比较签名是否一致
return generatedSign.equals(receivedSign);
diff --git a/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/tm/enums/PayStatus.java b/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/tm/enums/TmPayStatus.java
similarity index 79%
rename from smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/tm/enums/PayStatus.java
rename to smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/tm/enums/TmPayStatus.java
index ec1b55a1..de8a42f5 100644
--- a/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/tm/enums/PayStatus.java
+++ b/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/tm/enums/TmPayStatus.java
@@ -10,7 +10,7 @@ import lombok.Getter;
*/
@Getter
@AllArgsConstructor
-public enum PayStatus {
+public enum TmPayStatus {
SUCCESS("SUCCESS", "支付成功"),
NOTPAY("NOTPAY", "未支付"),
@@ -36,6 +36,15 @@ public enum PayStatus {
return SUCCESS.getCode().equals(code);
}
+ /**
+ * 判断支付状态是否成功
+ * @param status 支付状态
+ * @return 是否成功
+ */
+ public static boolean isSuccess(TmPayStatus status) {
+ return status != null && SUCCESS.getCode().equals(status.getCode());
+ }
+
/**
* 判断支付状态是否转入退款
* @param code 支付状态码
@@ -50,8 +59,8 @@ public enum PayStatus {
* @param code 支付状态码
* @return 对应的PayStatus枚举
*/
- public static PayStatus getByCode(String code) {
- for (PayStatus status : PayStatus.values()) {
+ public static TmPayStatus getByCode(String code) {
+ for (TmPayStatus status : TmPayStatus.values()) {
if (status.getCode().equals(code)) {
return status;
}
diff --git a/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/tm/enums/RefundStatus.java b/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/tm/enums/TmRefundStatus.java
similarity index 84%
rename from smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/tm/enums/RefundStatus.java
rename to smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/tm/enums/TmRefundStatus.java
index 49ab6b1a..826f2d64 100644
--- a/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/tm/enums/RefundStatus.java
+++ b/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/tm/enums/TmRefundStatus.java
@@ -10,7 +10,7 @@ import lombok.Getter;
*/
@Getter
@AllArgsConstructor
-public enum RefundStatus {
+public enum TmRefundStatus {
FAILED(0, "退款失败"),
REFUNDED(1, "转入退款");
@@ -31,8 +31,8 @@ public enum RefundStatus {
* @param code 状态码
* @return 对应的 RefundStatus 枚举
*/
- public static RefundStatus getByCode(int code) {
- for (RefundStatus status : RefundStatus.values()) {
+ public static TmRefundStatus getByCode(int code) {
+ for (TmRefundStatus status : TmRefundStatus.values()) {
if (status.getCode() == code) {
return status;
}
diff --git a/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/tm/vo/RefundInfo.java b/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/tm/vo/RefundInfo.java
index e0abca5f..bfd1dddf 100644
--- a/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/tm/vo/RefundInfo.java
+++ b/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/tm/vo/RefundInfo.java
@@ -1,6 +1,6 @@
package com.ruoyi.common.pay.tm.vo;
-import com.ruoyi.common.pay.tm.enums.RefundStatus;
+import com.ruoyi.common.pay.tm.enums.TmRefundStatus;
import lombok.Data;
/**
@@ -23,7 +23,7 @@ public class RefundInfo {
private String fromType; // 订单来源: wx, alipay, web, mini, pos, pc, desktop, api
private String refundTime; // 退款成功时间
private String refundMessage; // 退款失败原因
- private RefundStatus refundStatus; // 退款状态: RefundStatus 枚举
+ private TmRefundStatus refundStatus; // 退款状态: RefundStatus 枚举
private String refundAmount; // 已退款金额
private String createTime; // 创建时间
}
diff --git a/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/tm/vo/TmTradeInfo.java b/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/tm/vo/TmTradeInfo.java
index d6a1fbdc..aa7d822d 100644
--- a/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/tm/vo/TmTradeInfo.java
+++ b/smart-switch-ruoyi/smart-switch-common/src/main/java/com/ruoyi/common/pay/tm/vo/TmTradeInfo.java
@@ -1,6 +1,6 @@
package com.ruoyi.common.pay.tm.vo;
-import com.ruoyi.common.pay.tm.enums.PayStatus;
+import com.ruoyi.common.pay.tm.enums.TmPayStatus;
import lombok.Data;
@Data
@@ -132,7 +132,7 @@ public class TmTradeInfo {
* OPERATE_SETTLING:押金消费已受理;
* REVOKED_SUCCESS:预授权请求撤销成功
*/
- private PayStatus payStatus;
+ private TmPayStatus payStatus;
/**
* 支付时间
diff --git a/smart-switch-service/src/main/java/com/ruoyi/iot/service/IotService.java b/smart-switch-service/src/main/java/com/ruoyi/iot/service/IotService.java
index ada0c84b..52d00d75 100644
--- a/smart-switch-service/src/main/java/com/ruoyi/iot/service/IotService.java
+++ b/smart-switch-service/src/main/java/com/ruoyi/iot/service/IotService.java
@@ -1,9 +1,6 @@
package com.ruoyi.iot.service;
-import com.ruoyi.iot.domain.CurrentDeviceData;
-import com.ruoyi.iot.domain.HistoryDeviceData;
-import com.ruoyi.iot.domain.IotDeviceDetail;
import com.ruoyi.iot.domain.IotDeviceInfo;
import com.ruoyi.iot.domain.response.CommandResponse;
import com.ruoyi.iot.interfaces.IotDevice;
@@ -145,4 +142,14 @@ public interface IotService {
CommandResponse setWifi(IotDevice device, String wifiName, String wifiPwd);
CommandResponse setWifi(String mac, String productId, String wifiName, String wifiPwd);
+
+ /**
+ * 设置倒计时提醒
+ *
+ * @param device 设备
+ * @param seconds 倒计时(秒)
+ */
+ boolean setVoice(IotDevice device, long seconds);
+
+ boolean setVoice(String mac, String productId, long seconds);
}
diff --git a/smart-switch-service/src/main/java/com/ruoyi/iot/service/impl/IotServiceImpl.java b/smart-switch-service/src/main/java/com/ruoyi/iot/service/impl/IotServiceImpl.java
index e7c7d477..f8807982 100644
--- a/smart-switch-service/src/main/java/com/ruoyi/iot/service/impl/IotServiceImpl.java
+++ b/smart-switch-service/src/main/java/com/ruoyi/iot/service/impl/IotServiceImpl.java
@@ -31,8 +31,6 @@ import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
-import static org.bouncycastle.oer.its.Duration.seconds;
-
/**
* @author wjh
* 2024/3/20
@@ -452,5 +450,31 @@ public class IotServiceImpl implements IotService {
return null;
}
+ @Override
+ public boolean setVoice(IotDevice device, long seconds) {
+ if (device == null) {
+ return false;
+ }
+
+ try {
+ boolean res = this.setVoice(device.iotMac1(), device.getProductId(), seconds);
+ ServiceUtil.assertion(!res, "设备MAC1设置语音播报时间失败");
+ return true;
+ } catch (Exception e) {
+ log.warn("设备MAC1设置语音播报时间失败: {}", e.getMessage());
+ return this.setVoice(device.iotMac2(), device.getProductId(), seconds);
+ }
+ }
+
+ @Override
+ public boolean setVoice(String mac, String productId, long seconds) {
+ if (StringUtils.isBlank(mac) || StringUtils.isBlank(productId)) {
+ return false;
+ }
+ CommandResponse res = this.sendCommand(mac, IotConstants.COMMAND_SET_VOICE + seconds + IotConstants.COMMAND_SEPARATOR, productId);
+ ServiceUtil.assertion(!res.isSuccess(), "设置语音播报失败:" + res.getMsg());
+ return res.isSuccess();
+ }
+
}
diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/device/service/DeviceValidator.java b/smart-switch-service/src/main/java/com/ruoyi/ss/device/service/DeviceValidator.java
index e05f9e2e..ec948dfc 100644
--- a/smart-switch-service/src/main/java/com/ruoyi/ss/device/service/DeviceValidator.java
+++ b/smart-switch-service/src/main/java/com/ruoyi/ss/device/service/DeviceValidator.java
@@ -2,6 +2,7 @@ package com.ruoyi.ss.device.service;
import com.ruoyi.common.core.domain.ValidateResult;
import com.ruoyi.ss.device.domain.DeviceBO;
+import com.ruoyi.ss.device.domain.vo.DeviceVO;
import java.util.Collection;
import java.util.List;
@@ -50,4 +51,9 @@ public interface DeviceValidator {
* 判断MAC是否重复
*/
boolean isRepeatMac(Long deviceId, String mac);
+
+ /**
+ * 后校验
+ */
+ void afterCheck(DeviceVO vo);
}
diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/device/service/impl/DeviceServiceImpl.java b/smart-switch-service/src/main/java/com/ruoyi/ss/device/service/impl/DeviceServiceImpl.java
index 018aed23..08d2fa15 100644
--- a/smart-switch-service/src/main/java/com/ruoyi/ss/device/service/impl/DeviceServiceImpl.java
+++ b/smart-switch-service/src/main/java/com/ruoyi/ss/device/service/impl/DeviceServiceImpl.java
@@ -167,24 +167,26 @@ public class DeviceServiceImpl implements DeviceService
ServiceUtil.assertion(StringUtils.isBlank(data.getMac()), "参数错误,MAC不允许为空");
String key = data.getDeviceNo();
- ServiceUtil.assertion(!redisLock.lock(RedisLockKey.ADD_DEVICE, key), "当前录入人数过多,请稍后再试");
+ ServiceUtil.assertion(!redisLock.lock(RedisLockKey.ADD_DEVICE, key), "当前新增设备过于频繁,请稍后再试");
try {
- ServiceUtil.assertion(deviceValidator.isRepeatMac(data.getDeviceId(), data.getMac()), "MAC-1重复:" + data.getMac());
- ServiceUtil.assertion(deviceValidator.isRepeatMac(data.getDeviceId(), data.getMac2()), "MAC-2重复:" + data.getMac2());
- ServiceUtil.assertion(deviceValidator.isRepeatSn(data.getDeviceId(), data.getDeviceNo()), "SN重复");
SmModelVO model = modelService.selectSmModelByModelId(data.getModelId());
ServiceUtil.assertion(model == null, "型号不存在");
- ServiceUtil.assertion(StringUtils.isBlank(model.getProductId()), "型号产品ID为空");
+ ServiceUtil.assertion(StringUtils.isBlank(model.getProductId()), "型号产品ID未配置,请联系管理员处理");
data.setCreateTime(DateUtils.getNowDate());
data.setStatus(DeviceStatus.NORMAL.getStatus());
+ data.setOnlineStatus(DeviceOnlineStatus.OFFLINE.getStatus());
Integer result = transactionTemplate.execute(status -> {
// 创建设备
int insert = deviceMapper.insertSmDevice(data);
ServiceUtil.assertion(insert != 1, "新增设备失败");
+ // 后校验
+ DeviceVO vo = this.selectSmDeviceByDeviceId(data.getDeviceId());
+ deviceValidator.afterCheck(vo);
+
// 创建OneNet设备1
int code = iotService.create(data.getMac(), model.getProductId());
ServiceUtil.assertion(!IotHttpStatus.SUCCESS.equalCode(code) && !IotHttpStatus.DEVICE_EXIST.equalCode(code), "MAC-1注册失败");
@@ -209,11 +211,7 @@ public class DeviceServiceImpl implements DeviceService
*/
@Override
@Transactional
- public int updateSmDevice(DeviceBO data)
- {
- if (StringUtils.hasText(data.getDeviceNo())) {
- ServiceUtil.assertion(deviceValidator.isRepeatSn(data.getDeviceId(), data.getDeviceNo()), "SN重复");
- }
+ public int updateSmDevice(DeviceBO data) {
data.setUpdateTime(DateUtils.getNowDate());
@@ -222,6 +220,10 @@ public class DeviceServiceImpl implements DeviceService
int update = deviceMapper.updateSmDevice(data);
ServiceUtil.assertion(update != 1, "更新设备失败");
+ // 后校验
+ DeviceVO vo = this.selectSmDeviceByDeviceId(data.getDeviceId());
+ deviceValidator.afterCheck(vo);
+
// 更新套餐关联
if (data.getSuitIds() != null) {
// 删除设备套餐关联
diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/device/service/impl/DeviceValidatorImpl.java b/smart-switch-service/src/main/java/com/ruoyi/ss/device/service/impl/DeviceValidatorImpl.java
index 3cb7b68d..0d334566 100644
--- a/smart-switch-service/src/main/java/com/ruoyi/ss/device/service/impl/DeviceValidatorImpl.java
+++ b/smart-switch-service/src/main/java/com/ruoyi/ss/device/service/impl/DeviceValidatorImpl.java
@@ -3,6 +3,8 @@ package com.ruoyi.ss.device.service.impl;
import com.ruoyi.common.core.domain.BaseValidator;
import com.ruoyi.common.core.domain.ValidateResult;
import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.ServiceUtil;
+import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.collection.CollectionUtils;
import com.ruoyi.ss.device.domain.DeviceBO;
import com.ruoyi.ss.device.domain.DeviceQuery;
@@ -11,7 +13,6 @@ import com.ruoyi.ss.device.service.DeviceService;
import com.ruoyi.ss.device.service.DeviceValidator;
import com.ruoyi.ss.store.service.StoreValidator;
import com.ruoyi.ss.suit.service.SuitValidator;
-import org.apache.commons.lang.StringUtils;
import org.eclipse.jetty.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -159,4 +160,21 @@ public class DeviceValidatorImpl extends BaseValidator implements DeviceValidato
}
return false;
}
+
+ @Override
+ public void afterCheck(DeviceVO vo) {
+ if (vo == null) {
+ return;
+ }
+ if (StringUtils.hasText(vo.getMac()) || StringUtils.hasText(vo.getMac2())) {
+ ServiceUtil.assertion(Objects.equals(vo.getMac(), vo.getMac2()), "MAC-1和MAC-2不允许相同");
+ }
+ if (vo.getUserId() != null || vo.getAgentId() != null) {
+ ServiceUtil.assertion(Objects.equals(vo.getUserId(), vo.getAgentId()), "代理商和商户不允许是同一个用户");
+ }
+ ServiceUtil.assertion(this.isRepeatMac(vo.getDeviceId(), vo.getMac()), "MAC-1重复:" + vo.getMac());
+ ServiceUtil.assertion(this.isRepeatMac(vo.getDeviceId(), vo.getMac2()), "MAC-2重复:" + vo.getMac2());
+ ServiceUtil.assertion(this.isRepeatSn(vo.getDeviceId(), vo.getDeviceNo()), "SN重复");
+
+ }
}
diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/payBill/service/impl/PayBillServiceImpl.java b/smart-switch-service/src/main/java/com/ruoyi/ss/payBill/service/impl/PayBillServiceImpl.java
index fe42a9db..36c95e5c 100644
--- a/smart-switch-service/src/main/java/com/ruoyi/ss/payBill/service/impl/PayBillServiceImpl.java
+++ b/smart-switch-service/src/main/java/com/ruoyi/ss/payBill/service/impl/PayBillServiceImpl.java
@@ -5,6 +5,9 @@ import com.ruoyi.common.core.redis.enums.RedisLockKey;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.pay.syb.enums.SybTrxStatus;
import com.ruoyi.common.pay.syb.service.SybPayService;
+import com.ruoyi.common.pay.tm.TmPayService;
+import com.ruoyi.common.pay.tm.enums.TmPayStatus;
+import com.ruoyi.common.pay.tm.vo.TmTradeInfo;
import com.ruoyi.common.pay.wx.service.WxPayService;
import com.ruoyi.common.pay.wx.util.WxPayUtil;
import com.ruoyi.common.utils.DateUtils;
@@ -82,6 +85,9 @@ public class PayBillServiceImpl implements PayBillService
@Autowired
private SybPayService sybPayService;
+ @Autowired
+ private TmPayService tmPayService;
+
/**
* 查询支付订单
*
@@ -239,6 +245,10 @@ public class PayBillServiceImpl implements PayBillService
}
}
}
+ // 太米微信
+ else if (TransactionBillPayType.TM_WX.getType().equals(bill.getChannelId())) {
+ tmPayService.closeOrder(bill.getPayNo());
+ }
}
}
@@ -334,6 +344,8 @@ public class PayBillServiceImpl implements PayBillService
vo.setPayParams(wxPayService.prepayWithRequestPayment(bill));
} else if (TransactionBillPayType.TL_WX.getType().equals(bill.getChannelId())) {
vo.setPayParams(sybPayService.prepayWxApp(bill));
+ } else if (TransactionBillPayType.TM_WX.getType().equals(bill.getChannelId())) {
+ vo.setPayParams(tmPayService.pay(bill));
} else {
throw new ServiceException("暂不支持该支付方式");
}
@@ -518,6 +530,14 @@ public class PayBillServiceImpl implements PayBillService
} else {
return PayResultVO.fail("暂未支付成功");
}
+ } else if (TransactionBillPayType.TM_WX.getType().equals(bill.getChannelId())) {
+ // 太米微信支付
+ TmTradeInfo result = tmPayService.orderQuery(bill.getPayNo());
+ if (result != null && TmPayStatus.isSuccess(result.getPayStatus())) {
+ return PayResultVO.success(LocalDateTime.now()); // TODO 支付时间
+ } else {
+ return PayResultVO.fail("暂未支付成功");
+ }
}
return PayResultVO.fail("暂不支持该支付方式");
}
diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/refund/service/impl/RefundServiceImpl.java b/smart-switch-service/src/main/java/com/ruoyi/ss/refund/service/impl/RefundServiceImpl.java
index babba0be..93c9abec 100644
--- a/smart-switch-service/src/main/java/com/ruoyi/ss/refund/service/impl/RefundServiceImpl.java
+++ b/smart-switch-service/src/main/java/com/ruoyi/ss/refund/service/impl/RefundServiceImpl.java
@@ -3,6 +3,9 @@ package com.ruoyi.ss.refund.service.impl;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.pay.syb.enums.SybTrxStatus;
import com.ruoyi.common.pay.syb.service.SybPayService;
+import com.ruoyi.common.pay.tm.TmPayService;
+import com.ruoyi.common.pay.tm.enums.TmRefundStatus;
+import com.ruoyi.common.pay.tm.vo.RefundInfo;
import com.ruoyi.common.pay.wx.service.WxPayService;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ServiceUtil;
@@ -56,6 +59,9 @@ public class RefundServiceImpl implements RefundService
@Autowired
private ScheduledExecutorService scheduledExecutorService;
+ @Autowired
+ private TmPayService tmPayService;
+
/**
* 查询退款订单
@@ -204,7 +210,17 @@ public class RefundServiceImpl implements RefundService
this.handleRefundSuccess(refund.getRefundNo());
}, 0, TimeUnit.SECONDS);
}
- } else {
+ }
+ // 太米支付
+ else if (TransactionBillPayType.TM_WX.getType().equals(refund.getChannelId())) {
+ RefundInfo refundResult = tmPayService.refund(refundVO);
+ ServiceUtil.assertion(!TmRefundStatus.isSuccess(refundResult.getRefundStatus().getCode()), "发起退款失败:" + refundResult.getRefundMessage());
+ // 太米退款是同步通知,直接处理退款成功
+ scheduledExecutorService.schedule(() -> {
+ handleRefundSuccess(refund.getRefundNo());
+ }, 0, TimeUnit.SECONDS);
+ }
+ else {
throw new ServiceException("当前支付方式不支持退款");
}
diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/store/domain/StoreBO.java b/smart-switch-service/src/main/java/com/ruoyi/ss/store/domain/StoreBO.java
index 2075cba1..63682dde 100644
--- a/smart-switch-service/src/main/java/com/ruoyi/ss/store/domain/StoreBO.java
+++ b/smart-switch-service/src/main/java/com/ruoyi/ss/store/domain/StoreBO.java
@@ -30,6 +30,7 @@ public class StoreBO extends Store {
bo.setContactName(getContactName());
bo.setContactMobile(getContactMobile());
bo.setShow(getShow());
+ bo.setUseOutTime(getUseOutTime());
return bo;
}
@@ -52,6 +53,7 @@ public class StoreBO extends Store {
bo.setContactName(getContactName());
bo.setContactMobile(getContactMobile());
bo.setShow(getShow());
+ bo.setUseOutTime(getUseOutTime());
return bo;
}
@@ -76,6 +78,7 @@ public class StoreBO extends Store {
bo.setContactName(getContactName());
bo.setContactMobile(getContactMobile());
bo.setShow(getShow());
+ bo.setUseOutTime(getUseOutTime());
return bo;
}
@@ -102,6 +105,7 @@ public class StoreBO extends Store {
bo.setShow(getShow());
bo.setStatus(StoreStatus.NORMAL.getStatus());
bo.setEnabled(true);
+ bo.setUseOutTime(getUseOutTime());
return bo;
}
}
diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/suit/domain/Suit.java b/smart-switch-service/src/main/java/com/ruoyi/ss/suit/domain/Suit.java
index 807c3bfb..7c696c82 100644
--- a/smart-switch-service/src/main/java/com/ruoyi/ss/suit/domain/Suit.java
+++ b/smart-switch-service/src/main/java/com/ruoyi/ss/suit/domain/Suit.java
@@ -114,4 +114,14 @@ public class Suit extends BaseEntity
@Min(value = 0, message = "低功率关闭订单的功率值不允许小于0")
@JsonView(JsonViewProfile.App.class)
private BigDecimal lowPower;
+
+ @Excel(name = "是否开启结束前语音播报")
+ @ApiModelProperty("是否开启结束前语音播报")
+ @JsonView(JsonViewProfile.App.class)
+ private Boolean enabledVoice;
+
+ @Excel(name = "语音播报剩余时长", readConverterExp = "分=钟")
+ @ApiModelProperty("语音播报剩余时长(分钟)")
+ @JsonView(JsonViewProfile.App.class)
+ private BigDecimal voiceMinutes;
}
diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/suit/domain/SuitBO.java b/smart-switch-service/src/main/java/com/ruoyi/ss/suit/domain/SuitBO.java
index ea613d6c..54145135 100644
--- a/smart-switch-service/src/main/java/com/ruoyi/ss/suit/domain/SuitBO.java
+++ b/smart-switch-service/src/main/java/com/ruoyi/ss/suit/domain/SuitBO.java
@@ -35,6 +35,8 @@ public class SuitBO extends Suit {
bo.setGearTime(getGearTime());
bo.setEnabledLowPowerClose(getEnabledLowPowerClose());
bo.setLowPower(getLowPower());
+ bo.setEnabledVoice(getEnabledVoice());
+ bo.setVoiceMinutes(getVoiceMinutes());
return bo;
}
@@ -57,6 +59,8 @@ public class SuitBO extends Suit {
bo.setGearTime(getGearTime());
bo.setEnabledLowPowerClose(getEnabledLowPowerClose());
bo.setLowPower(getLowPower());
+ bo.setEnabledVoice(getEnabledVoice());
+ bo.setVoiceMinutes(getVoiceMinutes());
return bo;
}
}
diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/suit/mapper/SuitMapper.xml b/smart-switch-service/src/main/java/com/ruoyi/ss/suit/mapper/SuitMapper.xml
index f4f5a9e9..8f939977 100644
--- a/smart-switch-service/src/main/java/com/ruoyi/ss/suit/mapper/SuitMapper.xml
+++ b/smart-switch-service/src/main/java/com/ruoyi/ss/suit/mapper/SuitMapper.xml
@@ -30,6 +30,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
ss.gear_time,
ss.enabled_low_power_close,
ss.low_power,
+ ss.enabled_voice,
+ ss.voice_minutes,
su.user_name as user_name
from
@@ -48,9 +50,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
and ss.deleted = false
and ss.deleted = #{deleted}
and ss.user_id = #{userId}
- and fee_mode = #{feeMode}
- and fee_type = #{feeType}
- and enabled_low_power_close = #{enabledLowPowerClose}
+ and ss.fee_mode = #{feeMode}
+ and ss.fee_type = #{feeType}
+ and ss.enabled_low_power_close = #{enabledLowPowerClose}
+ and ss.enabled_voice = #{enabledVoice}
and ss.suit_id in (
select distinct sds.suit_id from ss_device_suit sds where sds.device_id = #{deviceId}
@@ -125,6 +128,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
gear_time,
enabled_low_power_close,
low_power,
+ enabled_voice,
+ voice_minutes,
#{name},
@@ -145,6 +150,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
#{gearTime,typeHandler=com.ruoyi.system.mapper.typehandler.IntegerSplitListTypeHandler},
#{enabledLowPowerClose},
#{lowPower},
+ #{enabledVoice},
+ #{voiceMinutes},
@@ -172,6 +179,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
gear_time = #{gearTime,typeHandler=com.ruoyi.system.mapper.typehandler.IntegerSplitListTypeHandler},
enabled_low_power_close = #{enabledLowPowerClose},
low_power = #{lowPower},
+ enabled_voice = #{enabledVoice},
+ voice_minutes = #{voiceMinutes},
diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/domain/TransactionBill.java b/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/domain/TransactionBill.java
index b9358453..08b7549e 100644
--- a/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/domain/TransactionBill.java
+++ b/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/domain/TransactionBill.java
@@ -290,6 +290,22 @@ public class TransactionBill extends BaseEntity implements Payable
@ApiModelProperty("代理商手机号")
private String agentMobile;
+ @Excel(name = "套餐是否开启语音播报")
+ @ApiModelProperty("套餐是否开启语音播报")
+ private Boolean suitEnabledVoid;
+
+ @Excel(name = "套餐语音播报阈值", readConverterExp = "分=钟")
+ @ApiModelProperty("套餐语音播报阈值")
+ private BigDecimal suitVoidMinute;
+
+ @Excel(name = "套餐语音播报设置结果", readConverterExp = "1=-成功,2-失败")
+ @ApiModelProperty("套餐语音播报设置结果")
+ private String suitVoidResult;
+
+ @Excel(name = "套餐语音播报设置结果描述")
+ @ApiModelProperty("套餐语音播报设置结果描述")
+ private String suitVoidMsg;
+
/**
* 获取价格(分)
*/
diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/domain/enums/RechargeVoiceStatus.java b/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/domain/enums/RechargeVoiceStatus.java
new file mode 100644
index 00000000..abc5942e
--- /dev/null
+++ b/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/domain/enums/RechargeVoiceStatus.java
@@ -0,0 +1,21 @@
+package com.ruoyi.ss.transactionBill.domain.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 语音开启状态
+ * @author wjh
+ * 2024/9/30
+ */
+@Getter
+@AllArgsConstructor
+public enum RechargeVoiceStatus {
+
+ SUCCESS("1", "成功"),
+ FAIL("0", "失败");
+
+ private final String status;
+ private final String msg;
+
+}
diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/domain/enums/TransactionBillPayType.java b/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/domain/enums/TransactionBillPayType.java
index c5541fc6..d634632c 100644
--- a/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/domain/enums/TransactionBillPayType.java
+++ b/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/domain/enums/TransactionBillPayType.java
@@ -24,8 +24,8 @@ public enum TransactionBillPayType {
ALI(2L, "支付宝", AccountType.ALIPAY),
BANK(3L, "银行卡", AccountType.BANK_CARD),
BALANCE(4L, "余额支付", null),
- TL_WX(5L, "通联微信支付", null)
- ;
+ TL_WX(5L, "通联微信支付", null),
+ TM_WX(6L, "太米微信支付", null);
private final Long type;
private final String name;
@@ -44,7 +44,10 @@ public enum TransactionBillPayType {
return Arrays.stream(types).map(TransactionBillPayType::getType).collect(Collectors.toList());
}
+ /**
+ * 微信支付列表
+ */
public static List wxList() {
- return asList(WECHAT, TL_WX);
+ return asList(WECHAT, TL_WX, TM_WX);
}
}
diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/mapper/TransactionBillMapper.xml b/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/mapper/TransactionBillMapper.xml
index 5ac6a6ae..2d70cd97 100644
--- a/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/mapper/TransactionBillMapper.xml
+++ b/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/mapper/TransactionBillMapper.xml
@@ -72,6 +72,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
stb.close_result,
stb.agent_id,
stb.agent_mobile,
+ stb.suit_enabled_void,
+ stb.suit_void_minute,
+ stb.suit_void_result,
+ stb.suit_void_msg,
@@ -192,6 +196,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
and stb.close_status = #{query.closeStatus}
and stb.agent_id = #{query.agentId}
and stb.agent_mobile like concat('%', #{query.agentMobile}, '%')
+ and stb.suit_enabled_void = #{query.suitEnabledVoid}
+ and stb.suit_void_result = #{query.suitVoidResult}
and
@@ -468,6 +474,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
close_result,
agent_id,
agent_mobile,
+ suit_enabled_void,
+ suit_void_minute,
+ suit_void_result,
+ suit_void_msg,
#{billNo},
@@ -528,6 +538,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
#{closeResult},
#{agentId},
#{agentMobile},
+ #{suitEnabledVoid},
+ #{suitVoidMinute},
+ #{suitVoidResult},
+ #{suitVoidMsg},
@@ -606,6 +620,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
stb.close_result = #{data.closeResult},
stb.agent_id = #{data.agentId},
stb.agent_mobile = #{data.agentMobile},
+ stb.suit_enabled_void = #{data.suitEnabledVoid},
+ stb.suit_void_minute = #{data.suitVoidMinute},
+ stb.suit_void_result = #{data.suitVoidResult},
+ stb.suit_void_msg = #{data.suitVoidMsg},
diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/service/impl/TransactionBillServiceImpl.java b/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/service/impl/TransactionBillServiceImpl.java
index 1bce4137..dc8359d3 100644
--- a/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/service/impl/TransactionBillServiceImpl.java
+++ b/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/service/impl/TransactionBillServiceImpl.java
@@ -447,6 +447,8 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
order.setSuitName(suit.getName());
order.setSuitEnableLowPowerClose(suit.getEnabledLowPowerClose());
order.setSuitLowPower(suit.getLowPower());
+ order.setSuitEnabledVoid(suit.getEnabledVoice());
+ order.setSuitVoidMinute(suit.getVoiceMinutes());
// 设备信息
order.setDeviceNo(dto.getDeviceNo());
@@ -954,14 +956,65 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
return updateCount;
});
- // 充值设备,尝试1次
+ // 操作成功
if (result != null && result == 1) {
+ // 充值设备,尝试1次
this.tryRechargeDevice(bill.getBillId(), 1);
+
+ // 设备设置语音播报
+ scheduledExecutorService.schedule(() -> {
+ this.trySetVoice(bill, 3);
+ }, 0, TimeUnit.SECONDS);
}
+
return result == null ? 0 : result;
}
+ /**
+ * 尝试设置语音播报
+ */
+ private void trySetVoice(TransactionBillVO bill, int tryCount) {
+ if (tryCount <= 0) {
+ return;
+ }
+ try {
+ transactionTemplate.execute(status -> {
+ // 设置为成功
+ int update = this.updateVoiceResult(bill.getBillId(), RechargeVoiceStatus.SUCCESS, "成功");
+ ServiceUtil.assertion(update != 1, "更新订单信息失败");
+
+ // 发送命令
+ boolean res = false;
+ if (bill.getSuitEnabledVoid() == null || !bill.getSuitEnabledVoid() || bill.getSuitVoidMinute() == null) {
+ res = iotService.setVoice(bill, 0L);
+ } else {
+ res = iotService.setVoice(bill, bill.getSuitVoidMinute().multiply(BigDecimal.valueOf(60)).longValue());
+ }
+ ServiceUtil.assertion(!res, "设备设置语音失败");
+
+ return res;
+ });
+ } catch (Exception e) {
+ log.info("订单设置设备语音失败:{}, 剩余次数:{}", bill.getBillNo(), tryCount - 1);
+ if (tryCount <= 1) {
+ // 设置为失败
+ int update = this.updateVoiceResult(bill.getBillId(), RechargeVoiceStatus.FAIL, e.getMessage());
+ ServiceUtil.assertion(update != 1, "更新订单信息失败");
+ } else {
+ this.trySetVoice(bill, tryCount - 1);
+ }
+ }
+ }
+
+ private int updateVoiceResult(Long billId, RechargeVoiceStatus status, String msg) {
+ TransactionBill data = new TransactionBill();
+ data.setBillId(billId);
+ data.setSuitVoidResult(status.getStatus());
+ data.setSuitVoidMsg(msg);
+ return transactionBillMapper.updateSmTransactionBill(data);
+ }
+
/**
* 异步尝试充值设备
* @param billId
@@ -971,14 +1024,12 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
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
diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/service/impl/TransactionBillValidatorImpl.java b/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/service/impl/TransactionBillValidatorImpl.java
index 0f1a17f1..3a5141a3 100644
--- a/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/service/impl/TransactionBillValidatorImpl.java
+++ b/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/service/impl/TransactionBillValidatorImpl.java
@@ -71,7 +71,7 @@ public class TransactionBillValidatorImpl extends BaseValidator implements Trans
if (store != null) {
LocalTime now = LocalTime.now();
if (!storeValidator.isBusinessTime(store, now)) {
- return error(String.format("当前店铺不在营业时间内,无法下单。营业时间:%s - %s", store.getBusinessTimeStart(), store.getBusinessTimeEnd()));
+ return error(String.format("请在营业时间内使用该设备!营业时间:%s - %s", store.getBusinessTimeStart(), store.getBusinessTimeEnd()));
}
}
diff --git a/smart-switch-web/src/main/java/com/ruoyi/web/controller/app/AppPayController.java b/smart-switch-web/src/main/java/com/ruoyi/web/controller/app/AppPayController.java
index 9e11ce78..831d593e 100644
--- a/smart-switch-web/src/main/java/com/ruoyi/web/controller/app/AppPayController.java
+++ b/smart-switch-web/src/main/java/com/ruoyi/web/controller/app/AppPayController.java
@@ -1,6 +1,7 @@
package com.ruoyi.web.controller.app;
import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
@@ -9,6 +10,8 @@ import com.ruoyi.common.pay.syb.enums.SybTrxCode;
import com.ruoyi.common.pay.syb.enums.SybTrxStatus;
import com.ruoyi.common.pay.syb.service.SybPayService;
import com.ruoyi.common.pay.syb.util.SybUtil;
+import com.ruoyi.common.pay.tm.TmPayService;
+import com.ruoyi.common.pay.tm.enums.TmPayStatus;
import com.ruoyi.common.pay.wx.domain.enums.WxNotifyEventType;
import com.ruoyi.common.pay.wx.domain.enums.WxTransferBatchStatus;
import com.ruoyi.common.pay.wx.util.WxPayUtil;
@@ -38,6 +41,8 @@ import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
+import java.time.LocalDateTime;
+import java.util.Map;
import java.util.TreeMap;
/**
@@ -65,6 +70,9 @@ public class AppPayController extends BaseController {
@Autowired
private TransactionBillConverter transactionBillConverter;
+ @Autowired
+ private TmPayService tmPayService;
+
@ApiOperation("微信支付充值订单")
@GetMapping("/wx/{billNo}")
public AjaxResult wxPay(@PathVariable @ApiParam("订单编号") String billNo) {
@@ -192,4 +200,35 @@ public class AppPayController extends BaseController {
}
}
+
+ /**
+ * 太米微信支付回调
+ */
+ @ApiOperation(value = "太米微信支付回调")
+ @PostMapping("/notify/tm")
+ public String tmwx(HttpServletRequest request) {
+ try {
+ String body = HttpUtils.getBody(request);
+ log.info("【太米微信支付回调】接收对象 : " + body);
+ // 先把body转成map
+ Map params = JSON.parseObject(body, Map.class);
+ // 验证签名
+ boolean sign = tmPayService.validSign(params);
+ if (sign) {
+ JSONObject tradeInfo = (JSONObject)params.get("tradeInfo");
+ String payType = tradeInfo.getString("payType"); // 交易类型
+ String outTradeId = tradeInfo.getString("outTradeId"); // 商户自定义订单号
+ String payStatus = tradeInfo.getString("payStatus"); // 交易结果
+ if(TmPayStatus.isSuccess(payStatus) && payType.equals("wx_pay")) {
+ payBillService.handleSuccess(outTradeId, LocalDateTime.now()); // TODO 支付时间待定
+ }
+ }else {
+ throw new ServiceException("签名验证失败");
+ }
+ return "{\"result\":\"SUCCESS\"}";
+ } catch (Exception e) {
+ throw new ServiceException(e.getMessage());
+ }
+ }
+
}
diff --git a/smart-switch-web/src/main/java/com/ruoyi/web/controller/app/AppTransactionBillController.java b/smart-switch-web/src/main/java/com/ruoyi/web/controller/app/AppTransactionBillController.java
index 437c1c82..ebdade50 100644
--- a/smart-switch-web/src/main/java/com/ruoyi/web/controller/app/AppTransactionBillController.java
+++ b/smart-switch-web/src/main/java/com/ruoyi/web/controller/app/AppTransactionBillController.java
@@ -282,7 +282,6 @@ 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)));
}
@@ -355,7 +354,6 @@ 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("这不是您的订单,无法支付");
diff --git a/smart-switch-web/src/main/resources/application-dev.yml b/smart-switch-web/src/main/resources/application-dev.yml
index 9474375e..7bf1795b 100644
--- a/smart-switch-web/src/main/resources/application-dev.yml
+++ b/smart-switch-web/src/main/resources/application-dev.yml
@@ -110,6 +110,15 @@ syb:
# 支付通知地址
notifyUrl: http://124.221.246.124:2290/app/pay/notify/tl
+# 太米支付
+tm:
+ developerId: "100232"
+ shopId: "0034947"
+ signKey: b4ixpiogfj5vu3tbkv23gj0dvo2j2ksz
+ httpUrl: https://v5.taimi100.com
+ sn: ""
+ notifyUrl: http://124.221.246.124:2290/app/pay/notify/tm
+
# 活体检测跳转地址
liveness:
returnUrl: http://192.168.2.81:3001/liveness