diff --git a/pom.xml b/pom.xml
index 31b7f8c4b..153629dc1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -298,6 +298,14 @@
+
+ com.tencentcloudapi
+ tencentcloud-sdk-java
+
+
+ 3.1.1000
+
+
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
index ad669aab8..adcd53a85 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
@@ -23,7 +23,7 @@ import com.ruoyi.system.service.ISysMenuService;
import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.web.controller.system.vo.*;
-import com.ruoyi.xkt.manager.AliAuthManager;
+import com.ruoyi.xkt.manager.TencentAuthManager;
import com.ruoyi.xkt.service.IStoreService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@@ -62,7 +62,7 @@ public class SysLoginController {
@Autowired
private RedisCache redisCache;
@Autowired
- private AliAuthManager aliAuthManager;
+ private TencentAuthManager tencentAuthManager;
@Autowired
private SysPasswordService passwordService;
@@ -75,8 +75,7 @@ public class SysLoginController {
@ApiOperation(value = "用户名密码登录")
@PostMapping("/loginByUname")
public AjaxResult login(@Validated @RequestBody LoginByUsernameVO loginBody) {
- boolean captchaPass = aliAuthManager.validate(loginBody.getLot_number(), loginBody.getCaptcha_output(),
- loginBody.getPass_token(), loginBody.getGen_time());
+ boolean captchaPass = tencentAuthManager.validate(loginBody.getTicket(), loginBody.getRandstr());
if (!captchaPass) {
return AjaxResult.error("验证失败");
}
@@ -110,8 +109,7 @@ public class SysLoginController {
@ApiOperation(value = "发送登录短信验证码")
@PostMapping("/sendSmsVerificationCode")
public R sendSmsVerificationCode(@Validated @RequestBody LoginSmsReqVO vo) {
- boolean captchaPass = aliAuthManager.validate(vo.getLot_number(), vo.getCaptcha_output(),
- vo.getPass_token(), vo.getGen_time());
+ boolean captchaPass = tencentAuthManager.validate(vo.getTicket(), vo.getRandstr());
if (!captchaPass) {
return R.fail("验证失败");
}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java
index 43a091d09..10398fdb2 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java
@@ -16,7 +16,7 @@ import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.web.controller.system.vo.LoginSmsReqVO;
import com.ruoyi.web.controller.system.vo.RegisterBySmsCodeVO;
import com.ruoyi.web.controller.xkt.vo.PhoneNumberVO;
-import com.ruoyi.xkt.manager.AliAuthManager;
+import com.ruoyi.xkt.manager.TencentAuthManager;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
@@ -48,7 +48,7 @@ public class SysRegisterController extends BaseController {
private ISysUserService userService;
@Autowired
- private AliAuthManager aliAuthManager;
+ private TencentAuthManager tencentAuthManager;
@ApiOperation(value = "档口供应商注册")
@PostMapping("/registerStore")
@@ -95,8 +95,7 @@ public class SysRegisterController extends BaseController {
@ApiOperation(value = "发送注册短信验证码")
@PostMapping("/sendSmsVerificationCode")
public R sendSmsVerificationCode(@Validated @RequestBody LoginSmsReqVO vo) {
- boolean captchaPass = aliAuthManager.validate(vo.getLot_number(), vo.getCaptcha_output(),
- vo.getPass_token(), vo.getGen_time());
+ boolean captchaPass = tencentAuthManager.validate(vo.getTicket(), vo.getRandstr());
if (!captchaPass) {
return R.fail("验证失败");
}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/vo/LoginByUsernameVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/vo/LoginByUsernameVO.java
index c5857bf4a..cff68d706 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/vo/LoginByUsernameVO.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/vo/LoginByUsernameVO.java
@@ -1,6 +1,6 @@
package com.ruoyi.web.controller.system.vo;
-import com.ruoyi.web.controller.xkt.vo.AliCaptchaAuthReqVO;
+import com.ruoyi.web.controller.xkt.vo.TencentCaptchaAuthReqVO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@@ -17,7 +17,7 @@ import javax.validation.constraints.NotEmpty;
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
-public class LoginByUsernameVO extends AliCaptchaAuthReqVO {
+public class LoginByUsernameVO extends TencentCaptchaAuthReqVO {
/**
* 用户名
*/
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/vo/LoginSmsReqVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/vo/LoginSmsReqVO.java
index 2f1be3930..b1aae905e 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/vo/LoginSmsReqVO.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/vo/LoginSmsReqVO.java
@@ -1,6 +1,6 @@
package com.ruoyi.web.controller.system.vo;
-import com.ruoyi.web.controller.xkt.vo.AliCaptchaAuthReqVO;
+import com.ruoyi.web.controller.xkt.vo.TencentCaptchaAuthReqVO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@@ -18,7 +18,7 @@ import javax.validation.constraints.Pattern;
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
-public class LoginSmsReqVO extends AliCaptchaAuthReqVO {
+public class LoginSmsReqVO extends TencentCaptchaAuthReqVO {
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
@NotEmpty(message = "手机号不能为空")
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/TencentCaptchaAuthReqVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/TencentCaptchaAuthReqVO.java
new file mode 100644
index 000000000..d33a6147e
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/TencentCaptchaAuthReqVO.java
@@ -0,0 +1,24 @@
+package com.ruoyi.web.controller.xkt.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotEmpty;
+
+/**
+ * @author liangyq
+ * @date 2025-07-22
+ */
+@ApiModel
+@Data
+public class TencentCaptchaAuthReqVO {
+
+ @NotEmpty(message = "ticket不能为空")
+ @ApiModelProperty("ticket(图像验证参数)")
+ private String ticket;
+
+ @NotEmpty(message = "randstr不能为空")
+ @ApiModelProperty("randstr(图像验证参数)")
+ private String randstr;
+}
diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml
index f5b60debe..444281df3 100644
--- a/ruoyi-admin/src/main/resources/application.yml
+++ b/ruoyi-admin/src/main/resources/application.yml
@@ -226,3 +226,11 @@ aliauth:
captcha:
appId: 386ec134856c9fe7d47ce2a34ee91038
appKey: 1b4e3ff703ca1ea0fb802d188079a25c
+
+# 腾讯认证
+tencent:
+ secretId: AKIDEbxNfmkW5RaVDhDc2Pcs198zpeP6kEZi
+ secretKey: 3ub7QZYN9qR4bxBE6qQs9GBuSnuoW0JP
+ captcha:
+ captchaAppId: 199022475
+ appSecretKey: wcqMdqjV3fnvFKxUAq5mwulnD
diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml
index d6fc361e9..006555dd0 100644
--- a/ruoyi-common/pom.xml
+++ b/ruoyi-common/pom.xml
@@ -193,6 +193,11 @@
1.16.1
+
+ com.tencentcloudapi
+ tencentcloud-sdk-java
+
+
\ No newline at end of file
diff --git a/xkt/src/main/java/com/ruoyi/xkt/manager/TencentAuthManager.java b/xkt/src/main/java/com/ruoyi/xkt/manager/TencentAuthManager.java
new file mode 100644
index 000000000..5fb11c2b1
--- /dev/null
+++ b/xkt/src/main/java/com/ruoyi/xkt/manager/TencentAuthManager.java
@@ -0,0 +1,70 @@
+package com.ruoyi.xkt.manager;
+
+import com.ruoyi.common.utils.ip.IpUtils;
+import com.tencentcloudapi.captcha.v20190722.CaptchaClient;
+import com.tencentcloudapi.captcha.v20190722.models.DescribeCaptchaResultRequest;
+import com.tencentcloudapi.captcha.v20190722.models.DescribeCaptchaResultResponse;
+import com.tencentcloudapi.common.AbstractModel;
+import com.tencentcloudapi.common.Credential;
+import com.tencentcloudapi.common.profile.ClientProfile;
+import com.tencentcloudapi.common.profile.HttpProfile;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author liangyq
+ * @date 2025-08-06
+ */
+@Slf4j
+@Component
+public class TencentAuthManager implements InitializingBean {
+
+ private static final Long SUCCESS_CODE = 1L;
+
+ @Value("${tencent.secretId:}")
+ private String secretId;
+ @Value("${tencent.secretKey:}")
+ private String secretKey;
+ @Value("${tencent.captcha.captchaAppId:}")
+ private Long captchaAppId;
+ @Value("${tencent.captcha.appSecretKey:}")
+ private String appSecretKey;
+
+ private CaptchaClient client;
+
+ @Override
+ public void afterPropertiesSet() throws Exception {
+ Credential cred = new Credential(secretId, secretKey);
+ // 实例化一个http选项,可选的,没有特殊需求可以跳过
+ HttpProfile httpProfile = new HttpProfile();
+ httpProfile.setEndpoint("captcha.tencentcloudapi.com");
+ // 实例化一个client选项,可选的,没有特殊需求可以跳过
+ ClientProfile clientProfile = new ClientProfile();
+ clientProfile.setHttpProfile(httpProfile);
+ // 实例化要请求产品的client对象,clientProfile是可选的
+ client = new CaptchaClient(cred, "", clientProfile);
+ }
+
+ public boolean validate(String ticket, String randstr) {
+ try {
+ DescribeCaptchaResultRequest req = new DescribeCaptchaResultRequest();
+ req.setCaptchaType(9L);
+ req.setTicket(ticket);
+ req.setRandstr(randstr);
+ req.setUserIp(IpUtils.getIpAddr());
+ req.setCaptchaAppId(captchaAppId);
+ req.setAppSecretKey(appSecretKey);
+ // 返回的resp是一个DescribeCaptchaResultResponse的实例,与请求对象对应
+ DescribeCaptchaResultResponse resp = client.DescribeCaptchaResult(req);
+ if (SUCCESS_CODE.equals(resp.getCaptchaCode())) {
+ return true;
+ }
+ log.warn("滑动验证未通过: {}", AbstractModel.toJsonString(resp));
+ } catch (Exception e) {
+ log.error("滑动验证校验异常", e);
+ }
+ return false;
+ }
+}