Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wecloud_im_server
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
hewei
wecloud_im_server
Commits
7ee8815c
Commit
7ee8815c
authored
Apr 25, 2022
by
Future
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
接短信验证码
parent
3fdcae4e
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
282 additions
and
13 deletions
+282
-13
config/src/main/resources/config/application-dev.yml
+9
-0
config/src/main/resources/config/application-prod.yml
+10
-2
config/src/main/resources/config/application-test.yml
+10
-2
core/pom.xml
+1
-5
core/src/main/java/com/wecloud/im/externalaccess/controller/VerifyCodeController.java
+18
-4
core/src/main/java/com/wecloud/im/externalaccess/service/UserService.java
+8
-0
core/src/main/java/com/wecloud/im/externalaccess/sms/constant/SmsConstants.java
+15
-0
core/src/main/java/com/wecloud/im/externalaccess/sms/domain/HwSmsResult.java
+18
-0
core/src/main/java/com/wecloud/im/externalaccess/sms/domain/HwSmsRoot.java
+17
-0
core/src/main/java/com/wecloud/im/externalaccess/sms/sender/HwSmsSender.java
+176
-0
No files found.
config/src/main/resources/config/application-dev.yml
View file @
7ee8815c
...
...
@@ -59,3 +59,12 @@ rocketmq:
namesrvAddr
:
127.0.0.1:9876
# 生产者的组名
producerId
:
im-server
sms
:
huawei
:
url
:
https://smsapi.cn-north-4.myhuaweicloud.com:443/sms/batchSendSms/v1
sender
:
8820122113125
appKey
:
FKFPgk3X6VRYAMJ9r9CIJWG2709W
appSecret
:
gvS2S8nD01vKCA1v45qi379gu1T5
verifyCode
:
666666
config/src/main/resources/config/application-prod.yml
View file @
7ee8815c
...
...
@@ -62,4 +62,13 @@ load-blance:
rocketmq
:
namesrvAddr
:
116.205.173.171:9876
# 生产者的组名
producerId
:
im-server
\ No newline at end of file
producerId
:
im-server
sms
:
huawei
:
url
:
https://smsapi.cn-north-4.myhuaweicloud.com:443/sms/batchSendSms/v1
sender
:
8820122113125
appKey
:
FKFPgk3X6VRYAMJ9r9CIJWG2709W
appSecret
:
gvS2S8nD01vKCA1v45qi379gu1T5
verifyCode
:
369258
config/src/main/resources/config/application-test.yml
View file @
7ee8815c
...
...
@@ -62,4 +62,13 @@ load-blance:
rocketmq
:
namesrvAddr
:
121.37.22.224:9876
# 生产者的组名
producerId
:
im-server
\ No newline at end of file
producerId
:
im-server
sms
:
huawei
:
url
:
https://smsapi.cn-north-4.myhuaweicloud.com:443/sms/batchSendSms/v1
sender
:
8820122113125
appKey
:
FKFPgk3X6VRYAMJ9r9CIJWG2709W
appSecret
:
gvS2S8nD01vKCA1v45qi379gu1T5
verifyCode
:
666666
core/pom.xml
View file @
7ee8815c
...
...
@@ -86,10 +86,6 @@
<groupId>
org.apache.httpcomponents
</groupId>
<artifactId>
httpcore
</artifactId>
</dependency>
<dependency>
<groupId>
org.apache.httpcomponents
</groupId>
<artifactId>
httpclient
</artifactId>
</dependency>
<!-- 友盟 start -->
...
...
@@ -102,7 +98,7 @@
<dependency>
<groupId>
org.apache.httpcomponents
</groupId>
<artifactId>
httpclient
</artifactId>
<version>
4.
3.5
</version>
<version>
4.
5.13
</version>
</dependency>
<!-- 友盟 end -->
...
...
core/src/main/java/com/wecloud/im/externalaccess/controller/VerifyCodeController.java
View file @
7ee8815c
package
com
.
wecloud
.
im
.
externalaccess
.
controller
;
import
com.alibaba.fastjson.JSONObject
;
import
com.wecloud.im.externalaccess.sms.constant.SmsConstants
;
import
com.wecloud.im.externalaccess.sms.sender.HwSmsSender
;
import
com.wecloud.utils.RandomUtil
;
import
io.geekidea.springbootplus.framework.common.api.ApiCode
;
import
io.geekidea.springbootplus.framework.common.api.ApiResult
;
import
io.geekidea.springbootplus.framework.common.controller.BaseController
;
...
...
@@ -26,6 +30,8 @@ import com.wecloud.im.externalaccess.service.UserService;
import
com.wecloud.im.sdk.enums.VerifySceneEnum
;
import
com.wecloud.im.ws.utils.RedisUtils
;
import
javax.annotation.Resource
;
/**
* @Author wenzhida
* @Date 2022/2/21 17:05
...
...
@@ -43,6 +49,9 @@ public class VerifyCodeController extends BaseController {
@Autowired
private
UserService
userService
;
@Resource
private
HwSmsSender
hwSmsSender
;
/**
* 发送验证码接口
*/
...
...
@@ -63,11 +72,16 @@ public class VerifyCodeController extends BaseController {
throw
new
BusinessException
(
"账号不存在"
);
}
}
// String verifyCode = RandomUtil.generateVerifyCode();
String
verifyCode
=
"666666"
;
String
verifyCode
=
RandomUtil
.
generateVerifyCode
();
String
key
=
new
StringBuilder
(
RedisKeyPrefixConstant
.
VERIFY_CODE_PREFIX
).
append
(
param
.
getVerifyScene
()).
append
(
param
.
getPhone
()).
toString
();
redisUtils
.
addKey
(
key
,
verifyCode
,
Duration
.
ofSeconds
(
3
*
60
));
// todo 接入短信推送
redisUtils
.
addKey
(
key
,
verifyCode
,
Duration
.
ofSeconds
(
5
*
60
));
// 短信发送
try
{
String
[]
templateParas
=
new
String
[]{
verifyCode
};
hwSmsSender
.
sendMsg
(
param
.
getPhone
(),
SmsConstants
.
TEMPLATE_ID
,
JSONObject
.
toJSONString
(
templateParas
));
}
catch
(
Exception
e
)
{
log
.
info
(
"发送短信异常 "
,
e
);
}
return
ApiResult
.
ok
();
}
...
...
core/src/main/java/com/wecloud/im/externalaccess/service/UserService.java
View file @
7ee8815c
...
...
@@ -7,6 +7,7 @@ import java.util.Date;
import
org.springframework.beans.BeanUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
...
...
@@ -56,6 +57,8 @@ import com.wecloud.utils.SnowflakeUtil;
@Service
public
class
UserService
extends
BaseServiceImpl
<
UserMapper
,
User
>
{
@Value
(
"${sms.huawei.verifyCode}"
)
private
String
verifyCode
;
@Autowired
private
RedisUtils
redisUtils
;
...
...
@@ -393,6 +396,11 @@ public class UserService extends BaseServiceImpl<UserMapper, User> {
* @param redisKey
*/
private
void
verifySMSVerifyCode
(
String
verifyCode
,
String
redisKey
)
{
if
(
verifyCode
.
equals
(
verifyCode
))
{
// 测试人员使用默认验证码
redisUtils
.
delKey
(
redisKey
);
return
;
}
String
verifyCodeInRedis
=
redisUtils
.
getKey
(
redisKey
);
if
(
verifyCodeInRedis
==
null
||
!
verifyCodeInRedis
.
equals
(
verifyCode
))
{
throw
new
BusinessException
(
"短信验证码不正确"
);
...
...
core/src/main/java/com/wecloud/im/externalaccess/sms/constant/SmsConstants.java
0 → 100644
View file @
7ee8815c
package
com
.
wecloud
.
im
.
externalaccess
.
sms
.
constant
;
/**
* @Author wenzhida
* @Date 2022/4/21 20:04
* @Description 短信常量
*/
public
class
SmsConstants
{
/**
* 验证码模板id
*/
public
static
String
TEMPLATE_ID
=
"352169b8e2904cd69595401f3cde2879"
;
}
core/src/main/java/com/wecloud/im/externalaccess/sms/domain/HwSmsResult.java
0 → 100644
View file @
7ee8815c
package
com
.
wecloud
.
im
.
externalaccess
.
sms
.
domain
;
import
lombok.Data
;
/**
* @Author wenzhida
* @Date 2022/4/21 20:01
* @Description 华为短信返回
*/
@Data
public
class
HwSmsResult
{
private
String
originTo
;
private
String
createTime
;
private
String
from
;
private
String
smsMsgId
;
private
String
status
;
}
core/src/main/java/com/wecloud/im/externalaccess/sms/domain/HwSmsRoot.java
0 → 100644
View file @
7ee8815c
package
com
.
wecloud
.
im
.
externalaccess
.
sms
.
domain
;
import
lombok.Data
;
import
java.util.List
;
/**
* @Author wenzhida
* @Date 2022/4/21 20:02
* @Description
*/
@Data
public
class
HwSmsRoot
{
private
List
<
HwSmsResult
>
result
;
private
String
code
;
private
String
description
;
}
core/src/main/java/com/wecloud/im/externalaccess/sms/sender/HwSmsSender.java
0 → 100644
View file @
7ee8815c
package
com
.
wecloud
.
im
.
externalaccess
.
sms
.
sender
;
import
com.alibaba.fastjson.JSONObject
;
import
com.wecloud.im.externalaccess.sms.domain.HwSmsRoot
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.codec.binary.Hex
;
import
org.apache.commons.codec.digest.DigestUtils
;
import
org.apache.http.HttpHeaders
;
import
org.apache.http.HttpResponse
;
import
org.apache.http.NameValuePair
;
import
org.apache.http.client.methods.RequestBuilder
;
import
org.apache.http.client.utils.URLEncodedUtils
;
import
org.apache.http.conn.ssl.NoopHostnameVerifier
;
import
org.apache.http.entity.StringEntity
;
import
org.apache.http.impl.client.CloseableHttpClient
;
import
org.apache.http.impl.client.HttpClients
;
import
org.apache.http.message.BasicNameValuePair
;
import
org.apache.http.ssl.SSLContextBuilder
;
import
org.apache.http.util.EntityUtils
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.stereotype.Component
;
import
java.nio.charset.Charset
;
import
java.text.SimpleDateFormat
;
import
java.util.ArrayList
;
import
java.util.Base64
;
import
java.util.Date
;
import
java.util.List
;
import
java.util.UUID
;
/**
* @Author wenzhida
* @Date 2022/4/21 21:30
* @Description 华为短信发送器
*/
@Slf4j
@Component
public
class
HwSmsSender
{
/**
* 无需修改,用于格式化鉴权头域,给"X-WSSE"参数赋值
*/
private
static
final
String
WSSE_HEADER_FORMAT
=
"UsernameToken Username=\"%s\",PasswordDigest=\"%s\",Nonce=\"%s\",Created=\"%s\""
;
/**
* 无需修改,用于格式化鉴权头域,给"Authorization"参数赋值
*/
private
static
final
String
AUTH_HEADER_VALUE
=
"WSSE realm=\"SDP\",profile=\"UsernameToken\",type=\"Appkey\""
;
@Value
(
"${sms.huawei.url}"
)
private
String
url
;
@Value
(
"${sms.huawei.sender}"
)
private
String
sender
;
@Value
(
"${sms.huawei.appKey}"
)
private
String
appKey
;
@Value
(
"${sms.huawei.appSecret}"
)
private
String
appSecret
;
public
String
sendMsg
(
String
mobile
,
String
templateId
,
String
templateParas
)
throws
Exception
{
//条件必填,国内短信关注,当templateId指定的模板类型为通用模板时生效且必填,必须是已审核通过的,与模板类型一致的签名名称
//国际/港澳台短信不用关注该参数
//签名名称
String
signature
=
"蔚可云"
;
String
receiver
=
"+86"
+
mobile
;
//选填,短信状态报告接收地址,推荐使用域名,为空或者不填表示不接收状态报告
String
statusCallBack
=
""
;
/**
* 选填,使用无变量模板时请赋空值 String templateParas = "";
* 单变量模板示例:模板内容为"您的验证码是${1}"时,templateParas可填写为"[\"369751\"]"
* 双变量模板示例:模板内容为"您有${1}件快递请到${2}领取"时,templateParas可填写为"[\"3\",\"人民公园正门\"]"
* 模板中的每个变量都必须赋值,且取值不能为空
* 查看更多模板和变量规范:产品介绍>模板和变量规范
*/
//模板变量,此处以单变量验证码短信为例,请客户自行生成6位验证码,并定义为字符串类型,以杜绝首位0丢失的问题(例如:002569变成了2569)。
//templateParas = "[\"369751\"]";
//请求Body,不携带签名名称时,signature请填null
String
body
=
buildRequestBody
(
sender
,
receiver
,
templateId
,
templateParas
,
statusCallBack
,
signature
);
if
(
null
==
body
||
body
.
isEmpty
())
{
log
.
info
(
"body is null."
);
return
"1"
;
}
//请求Headers中的X-WSSE参数值
String
wsseHeader
=
buildWsseHeader
(
appKey
,
appSecret
);
if
(
null
==
wsseHeader
||
wsseHeader
.
isEmpty
())
{
log
.
info
(
"wsse header is null."
);
return
"1"
;
}
//为防止因HTTPS证书认证失败造成API调用失败,需要先忽略证书信任问题
CloseableHttpClient
client
=
HttpClients
.
custom
()
.
setSSLContext
(
new
SSLContextBuilder
().
loadTrustMaterial
(
null
,
(
x509CertChain
,
authType
)
->
true
).
build
())
.
setSSLHostnameVerifier
(
NoopHostnameVerifier
.
INSTANCE
)
.
build
();
//请求方法POST
HttpResponse
response
=
client
.
execute
(
RequestBuilder
.
create
(
"POST"
)
.
setUri
(
url
)
.
addHeader
(
HttpHeaders
.
CONTENT_TYPE
,
"application/x-www-form-urlencoded"
)
.
addHeader
(
HttpHeaders
.
AUTHORIZATION
,
AUTH_HEADER_VALUE
)
.
addHeader
(
"X-WSSE"
,
wsseHeader
)
.
setEntity
(
new
StringEntity
(
body
)).
build
());
//打印响应头域信息
log
.
info
(
"响应头信息 {}"
,
response
.
toString
());
//打印响应消息实体
String
entity
=
EntityUtils
.
toString
(
response
.
getEntity
());
log
.
info
(
"消息实体 {}"
,
entity
);
HwSmsRoot
hwSmsRoot
=
JSONObject
.
parseObject
(
entity
,
HwSmsRoot
.
class
);
return
"0"
;
}
/**
* 构造请求Body体
*
* @param sender
* @param receiver
* @param templateId
* @param templateParas
* @param statusCallbackUrl
* @param signature | 签名名称,使用国内短信通用模板时填写
* @return
*/
static
String
buildRequestBody
(
String
sender
,
String
receiver
,
String
templateId
,
String
templateParas
,
String
statusCallbackUrl
,
String
signature
)
{
if
(
null
==
sender
||
null
==
receiver
||
null
==
templateId
||
sender
.
isEmpty
()
||
receiver
.
isEmpty
()
||
templateId
.
isEmpty
())
{
System
.
out
.
println
(
"buildRequestBody(): sender, receiver or templateId is null."
);
return
null
;
}
List
<
NameValuePair
>
keyValues
=
new
ArrayList
<
NameValuePair
>();
keyValues
.
add
(
new
BasicNameValuePair
(
"from"
,
sender
));
keyValues
.
add
(
new
BasicNameValuePair
(
"to"
,
receiver
));
keyValues
.
add
(
new
BasicNameValuePair
(
"templateId"
,
templateId
));
if
(
null
!=
templateParas
&&
!
templateParas
.
isEmpty
())
{
keyValues
.
add
(
new
BasicNameValuePair
(
"templateParas"
,
templateParas
));
}
if
(
null
!=
statusCallbackUrl
&&
!
statusCallbackUrl
.
isEmpty
())
{
keyValues
.
add
(
new
BasicNameValuePair
(
"statusCallback"
,
statusCallbackUrl
));
}
if
(
null
!=
signature
&&
!
signature
.
isEmpty
())
{
keyValues
.
add
(
new
BasicNameValuePair
(
"signature"
,
signature
));
}
return
URLEncodedUtils
.
format
(
keyValues
,
Charset
.
forName
(
"UTF-8"
));
}
/**
* 构造X-WSSE参数值
*
* @param appKey
* @param appSecret
* @return
*/
static
String
buildWsseHeader
(
String
appKey
,
String
appSecret
)
{
if
(
null
==
appKey
||
null
==
appSecret
||
appKey
.
isEmpty
()
||
appSecret
.
isEmpty
())
{
System
.
out
.
println
(
"buildWsseHeader(): appKey or appSecret is null."
);
return
null
;
}
SimpleDateFormat
sdf
=
new
SimpleDateFormat
(
"yyyy-MM-dd'T'HH:mm:ss'Z'"
);
//Created
String
time
=
sdf
.
format
(
new
Date
());
//Nonce
String
nonce
=
UUID
.
randomUUID
().
toString
().
replace
(
"-"
,
""
);
byte
[]
passwordDigest
=
DigestUtils
.
sha256
(
nonce
+
time
+
appSecret
);
String
hexDigest
=
Hex
.
encodeHexString
(
passwordDigest
);
String
passwordDigestBase64Str
=
Base64
.
getEncoder
().
encodeToString
(
hexDigest
.
getBytes
());
return
String
.
format
(
WSSE_HEADER_FORMAT
,
appKey
,
passwordDigestBase64Str
,
nonce
,
time
);
}
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment