提交 71bacad6 authored 作者: 李秋林's avatar 李秋林

腾讯云-短信服务工具类添加;促销员注册手机验证码进行验证

上级 b1f6c41d
......@@ -144,6 +144,17 @@
<version>3.1.998</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.4.2</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
</dependencies>
<build>
......
package com.wangxiaolu.promotion.common.redis;
import lombok.AllArgsConstructor;
import lombok.Getter;
public interface RedisKeys {
@AllArgsConstructor
@Getter
enum UserKeys {
/**
* 用户接收手机验证码
*/
PHONE_VER_CODE("user:phone_"),
;
String key;
}
}
package com.wangxiaolu.promotion.common.redis.service;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
@Component
public class RedisCache {
@Autowired
RedisTemplate<String, String> redisTemplate;
/**
* 保存一个值
*/
public void add(String key, String val) {
ValueOperations<String, String> vo = redisTemplate.opsForValue();
vo.set(key, val);
}
/**
* 保存一个值,设置过期时间(分钟)
*/
public void addToMinute(String key, String val, long time) {
ValueOperations<String, String> vo = redisTemplate.opsForValue();
vo.set(key, val, time, TimeUnit.MINUTES);
}
/**
* 保存一个值,并将val json化
*/
public void addToJson(String key, Object val) {
ValueOperations<String, String> vo = redisTemplate.opsForValue();
vo.set(key, valToJson(val));
}
/**
* 保存一个值,并将val json化,设置过期时间(分钟)
*/
public void addToJsonToMinute(String key, Object val, long time) {
ValueOperations<String, String> vo = redisTemplate.opsForValue();
vo.set(key, valToJson(val), time, TimeUnit.MINUTES);
}
/**
* 获取一个值
*/
public String get(String key) {
ValueOperations<String, String> vo = redisTemplate.opsForValue();
return vo.get(key);
}
/**
* 获取一个值,并将val json化
*/
public JSONObject getToJson(String key) {
ValueOperations<String, String> vo = redisTemplate.opsForValue();
String val = vo.get(key);
return JSONObject.parseObject(val);
}
/**
* 获取一个值,并将val json化
*/
// public JSONObject getUserJsonInfo(String authorization) {
// JSONObject userDetail = getToJson(RedisKeys.UserKeys.TOKEN.getKey() + authorization);
// return userDetail;
// }
public void removeKey(String key) {
redisTemplate.delete(key);
}
private String valToJson(Object o) {
return JSONObject.toJSONString(o);
}
}
package com.wangxiaolu.promotion.controller.tengxunyun;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author : liqiulin
* @date : 2024-04-15 14
* @describe : 验证、控制相关数据接口
*/
@Slf4j
@RestController
@RequestMapping("/console/query")
public class ConsoleDataQueryController {
/**
* 查询验证码
*/
}
package com.wangxiaolu.promotion.controller.tengxunyun;
import com.wangxiaolu.promotion.exception.ParamException;
import com.wangxiaolu.promotion.result.basedata.RCode;
import com.wangxiaolu.promotion.service.user.TencentCoreService;
import com.wangxiaolu.promotion.utils.DataUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
/**
* @author : liqiulin
* @date : 2024-04-15 11
* @describe : 对接腾讯云接口
* 如:腾讯云短信
*/
@Slf4j
@RestController
@RequestMapping("/tencent/core")
public class TencentCoreController {
@Autowired
TencentCoreService tencentCoreService;
/**
* 腾讯云短信
*/
@PostMapping("/send/sms")
public void sendSms(@RequestBody Map<String, String> phoneInfo) {
String phone = phoneInfo.get("phone");
if (StringUtils.isEmpty(phone) || !DataUtils.phonePattern(phone)) {
throw new ParamException(RCode.PHONE_PARAM_ERROR, null);
}
tencentCoreService.sendSmsPhoneVerCOde(phone);
}
}
package com.wangxiaolu.promotion.controller.wechat;
import com.alibaba.fastjson.JSONObject;
import com.wangxiaolu.promotion.common.redis.RedisKeys;
import com.wangxiaolu.promotion.common.redis.service.RedisCache;
import com.wangxiaolu.promotion.exception.ParamException;
import com.wangxiaolu.promotion.pojo.user.dto.WxTemporaryInfoDto;
import com.wangxiaolu.promotion.pojo.user.vo.WxJsUserInfoVo;
......@@ -8,6 +10,7 @@ import com.wangxiaolu.promotion.result.basedata.RCode;
import com.wangxiaolu.promotion.service.wechat.WeChatUserCoreService;
import com.wangxiaolu.promotion.utils.DataUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
......@@ -28,22 +31,28 @@ public class WeChatUserCoreController {
@Autowired
WeChatUserCoreService weChatUserCoreService;
@Autowired
RedisCache redisCache;
/**
* 促销员注册信息
*/
@PostMapping("/temporary/enroll")
public boolean enrollUserInfo(@RequestBody @Validated WxJsUserInfoVo wxJsUserInfoVo) {
log.info("微信-促销员注册:{}", JSONObject.toJSONString(wxJsUserInfoVo));
// 人员信息校验
boolean isIden = DataUtils.idenCardPattern(wxJsUserInfoVo.getIdenNumber());
boolean isPhone = DataUtils.phonePattern(wxJsUserInfoVo.getPhone());
if (!isIden || !isPhone) {
throw new ParamException(RCode.ENROLL_PARAM_ERROR, null);
}
// todo 手机号校验 wxJsUserInfoVo.getPhoneCode()
log.info("微信-促销员注册:{}", JSONObject.toJSONString(wxJsUserInfoVo));
// 手机号-验证码 校验
String redisKey = RedisKeys.UserKeys.PHONE_VER_CODE.getKey() + wxJsUserInfoVo.getPhone();
String phoneCodeOld = redisCache.get(redisKey);
if (StringUtils.isBlank(phoneCodeOld) || !phoneCodeOld.equals(wxJsUserInfoVo.getPhoneCode())){
throw new ParamException(RCode.TENCENT_SMS_PHONE_CODE_ERROR, null);
}
WxTemporaryInfoDto temporaryDto = new WxTemporaryInfoDto();
BeanUtils.copyProperties(wxJsUserInfoVo, temporaryDto);
......
......@@ -30,7 +30,14 @@ public enum RCode implements StatusCode {
*/
LOGIN_PARAM_ERROR(3000, "登录信息错误"),
ENROLL_PARAM_ERROR(3001, "注册信息错误"),
PHONE_PARAM_ERROR(3002, "注册信息错误"),
PHONE_PARAM_ERROR(3002, "手机号异常"),
/**
* 腾讯云
* 3500+
*/
TENCENT_SMS_ERROR(3500, "短信发送失败"),
TENCENT_SMS_REPETITION(3501, "短信已发送"),
TENCENT_SMS_PHONE_CODE_ERROR(3502, "验证码错误"),
;
......
package com.wangxiaolu.promotion.service.user;
/**
* @author : liqiulin
* @date : 2024-04-15 15
* @describe :
*/
public interface TencentCoreService {
/**
* 发送手机号验证码
* @param phone 手机号
*/
void sendSmsPhoneVerCOde(String phone);
}
package com.wangxiaolu.promotion.service.user.impl;
import com.wangxiaolu.promotion.common.redis.RedisKeys;
import com.wangxiaolu.promotion.common.redis.service.RedisCache;
import com.wangxiaolu.promotion.exception.ParamException;
import com.wangxiaolu.promotion.result.basedata.RCode;
import com.wangxiaolu.promotion.service.user.TencentCoreService;
import com.wangxiaolu.promotion.utils.DataUtils;
import com.wangxiaolu.promotion.utils.TencentUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
/**
* @author : liqiulin
* @date : 2024-04-15 15
* @describe :
*/
@Slf4j
@Service
public class TencentCoreServiceImpl implements TencentCoreService {
@Value("${tengxunyun.sms.overdue_long}")
private long overdueLong;
@Autowired
TencentUtils tencentUtils;
@Autowired
RedisCache redisCache;
@Override
public void sendSmsPhoneVerCOde(String phone) {
String redisKey = RedisKeys.UserKeys.PHONE_VER_CODE.getKey() + phone;
// 判断是否已获取
String verCodeOld = redisCache.get(redisKey);
if (StringUtils.isNotBlank(verCodeOld)){
throw new ParamException(RCode.TENCENT_SMS_REPETITION, null);
}
// 生成6位验证码
String phoneVerCode = DataUtils.phoneVerCode();
log.info("腾讯云短信,发送验证码:{}-{}", phone, phoneVerCode);
redisCache.addToMinute(redisKey, phoneVerCode, overdueLong);
// boolean succss = tencentUtils.sendSmsPhoneVerCOde(phone, phoneVerCode);
boolean succss = true;
if (!succss) {
redisCache.removeKey(redisKey);
log.info("腾讯云短信发送失败:删除验证码:{}-{}", phone, phoneVerCode);
}
}
}
package com.wangxiaolu.promotion.controller.tengxunyun;
package com.wangxiaolu.promotion.utils;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
......@@ -7,66 +7,74 @@ import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.sms.v20210111.SmsClient;
import com.tencentcloudapi.sms.v20210111.models.SendSmsRequest;
import com.tencentcloudapi.sms.v20210111.models.SendSmsResponse;
import com.tencentcloudapi.sms.v20210111.models.SendStatus;
import com.wangxiaolu.promotion.exception.ParamException;
import com.wangxiaolu.promotion.result.basedata.RCode;
import com.wangxiaolu.promotion.utils.DataUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
import org.springframework.stereotype.Component;
/**
* @author : liqiulin
* @date : 2024-04-15 11
* @describe : 对接腾讯云接口
* 如:腾讯云短信
* @date : 2024-04-15 15
* @describe :
*/
@Slf4j
@RestController
@RequestMapping("/tencent")
public class TengXunYunController {
@Component
public class TencentUtils {
/**
* tengxunyun.sms
*/
@Value("${tengxunyun.secret_d}")
private String secretId;
@Value("${tengxunyun.secret_key}")
private String secretKey;
/**
* tengxunyun.sms
*/
@Value("${tengxunyun.sms.endpoint_beijing}")
private String endpointBeijing;
@Value("${tengxunyun.sms.ap_beijing}")
private String apBeijing;
@Value("${tengxunyun.sms.sdk_app_id_defult}")
private String sdkAppIdDefult;
@Value("${tengxunyun.sms.sign_name}")
private String signName;
@Value("${tengxunyun.sms.template_id}")
private String templateId;
@Value("${tengxunyun.sms.sign_name_a}")
private String signNameA;
@Value("${tengxunyun.sms.template_id_a}")
private String templateIdA;
@Value("${tengxunyun.sms.overdue_long}")
private String overdueLong;
private long overdueLong;
/**
* 腾讯云短信
* 给指定手机号发送验证码
*
* @param phone 手机号(1个)
*/
@PostMapping("/send/sms")
public void sendSms(Map<String, String> phoneInfo) {
String phone = phoneInfo.get("phone");
if (StringUtils.isEmpty(phone) || !DataUtils.phonePattern(phone)) {
throw new ParamException(RCode.PHONE_PARAM_ERROR, null);
}
// todo 生成6位验证码并且放到redis中
String phoneVerCode = DataUtils.phoneVerCode();
System.out.println("生成验证码:" + phoneVerCode);
public boolean sendSmsPhoneVerCOde(String phone, String phoneVerCode) {
String signName = signNameA;
String templateId = templateIdA;
String[] templateParamSet = {phoneVerCode, Long.toString(overdueLong)};
String[] phoneNumberSet = {"+86" + phone};
try {
SendSmsResponse res = sendSms(templateParamSet, phoneNumberSet, signName, templateId);
SendStatus sendStatus = res.getSendStatusSet()[0];
if (StringUtils.isBlank(sendStatus.getCode()) || !sendStatus.getCode().contains("OK")) {
return false;
}
return true;
}
/**
* 必要步骤
* 核心工具:发送短信
* @return 发送结果
*/
private SendSmsResponse sendSms(String[] templateParamSet, String[] phoneNumberSet, String signName, String templateId) {
try {
// 必要步骤
// 1、实例化一个认证对象
Credential cred = new Credential(secretId, secretKey);
// 2、实例化http选项,SDK默认使用POST方法,GET方法无法处理一些较大的请求(非必要不使用);SDK有默认的超时时间,非必要请不要进行调整
......@@ -75,10 +83,7 @@ public class TengXunYunController {
httpProfile.setConnTimeout(60);
httpProfile.setEndpoint(endpointBeijing);
/**
* 非必要步骤
*/
// 非必要步骤
// 1、例化一个客户端配置对象
ClientProfile clientProfile = new ClientProfile();
/* SDK默认用TC3-HMAC-SHA256进行签名
......@@ -92,18 +97,11 @@ public class TengXunYunController {
req.setSmsSdkAppId(sdkAppIdDefult);
req.setSignName(signName);
req.setTemplateId(templateId);
/**
* 模板参数
* index0:验证码;index1:过期时间(分钟)
*/
String[] templateParamSet = {"654321", overdueLong};
// 参数列表:index0:验证码;index1:过期时间(分钟)
req.setTemplateParamSet(templateParamSet);
/**
* 下发手机号码,采用E.164标准(+[国家或地区码][手机号]),最多不要超过200个手机号
*/
String E164 = "+86";
String[] phoneNumberSet = {E164 + "15701654502", phoneVerCode};
// 下发手机号码,采用E.164标准(+[国家或地区码][手机号]),最多不要超过200个手机号
req.setPhoneNumberSet(phoneNumberSet);
/* 用户的 session 内容(无需要可忽略): 可以携带用户侧 ID 等上下文信息,server 会原样返回 */
......@@ -117,16 +115,16 @@ public class TengXunYunController {
req.setSenderId(senderid);
/* 通过 client 对象调用 SendSms 方法发起请求。注意请求方法名与请求对象是对应的
* 返回的 res 是一个 SendSmsResponse 类的实例,与请求对象对应 */
SendSmsResponse res = client.SendSms(req);
// 输出json格式的字符串回包,或者取出单个值:System.out.println(res.getRequestId());
System.out.println(SendSmsResponse.toJsonString(res));
log.info("腾讯云-短信发送结果:{}", SendSmsResponse.toJsonString(res));
return res;
} catch (TencentCloudSDKException e) {
log.error("腾讯云-短信服务,SMS发送异常:{}", e.getMessage());
throw new ParamException(RCode.PHONE_PARAM_ERROR, null);
throw new ParamException(RCode.TENCENT_SMS_ERROR, null);
}
}
}
......@@ -43,8 +43,8 @@ tengxunyun:
# 应用ID
sdk_app_id_defult: 1400903035
# 模板名称
sign_name: 北京王小卤
sign_name_a: 北京王小卤
# 模板ID
template_id: 2127434
template_id_a: 2127434
# 验证码过期时间(分钟)
overdue_long: 5
\ No newline at end of file
package com.wangxiaolu.promotion.controller.tengxunyun;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.HashMap;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.*;
/**
* @author : liqiulin
* @date : 2024-04-15 14
* @describe :
*/
@SpringBootTest
@RunWith(SpringRunner.class)
class TencentCoreControllerTest {
@Autowired
TencentCoreController tencentCoreController;
@Test
void sendSms() {
Map<String,String> phoneInfo = new HashMap<>();
phoneInfo.put("phone","15701654502");
tencentCoreController.sendSms(phoneInfo);
}
}
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论