Toggle navigation
Toggle navigation
This project
Loading...
Sign in
jiujian
/
client-customer-order-api
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Authored by
zhuyifan
2025-05-19 18:40:59 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
99c13c0e0f31ce5bc1f80b33912f2ba95ba87eae
99c13c0e
1 parent
9843b09b
feat(service): 实现微信 access_token 缓存机制
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
74 additions
and
2 deletions
src/main/java/com/infoloop/tianting/config/AppConfig.java
src/main/java/com/infoloop/tianting/constant/RedisKeyConstants.java
src/main/java/com/infoloop/tianting/service/client/WxMiniProgramHttpClient.java
src/main/java/com/infoloop/tianting/store/WxAccessTokenStore.java
src/main/java/com/infoloop/tianting/config/AppConfig.java
View file @
99c13c0
...
...
@@ -7,6 +7,7 @@ import com.infoloop.tianting.server.StorageService;
import
com.infoloop.tianting.server.StorageServiceFactory
;
import
com.infoloop.tianting.store.LoginCodeStore
;
import
com.infoloop.tianting.store.WeeklyTaskStore
;
import
com.infoloop.tianting.store.WxAccessTokenStore
;
import
com.infoloop.tianting.utils.SmsUtil
;
import
io.lettuce.core.api.StatefulRedisConnection
;
import
org.springframework.beans.factory.annotation.Autowired
;
...
...
@@ -33,6 +34,12 @@ public class AppConfig {
}
@Bean
public
WxAccessTokenStore
wxAccessTokenStore
(
@Autowired
@Qualifier
(
REDIS_CONNECTION
)
final
StatefulRedisConnection
<
String
,
String
>
connection
)
{
final
var
commands
=
connection
.
sync
();
return
new
WxAccessTokenStore
(
commands
,
7000
);
}
@Bean
public
WeeklyTaskStore
weeklyTaskStore
(
@Autowired
@Qualifier
(
REDIS_CONNECTION
)
final
StatefulRedisConnection
<
String
,
String
>
connection
)
{
final
var
commands
=
connection
.
sync
();
final
var
expireSeconds
=
Duration
.
ofDays
(
8
).
getSeconds
();
...
...
src/main/java/com/infoloop/tianting/constant/RedisKeyConstants.java
View file @
99c13c0
...
...
@@ -4,6 +4,8 @@ public class RedisKeyConstants {
public
static
final
String
REPEAT_SUBMIT
=
"REPEAT_SUBMIT"
;
public
static
final
String
WX_ACCESS_TOKEN
=
"WX_ACCESS_TOKEN"
;
public
static
String
getSMSCodeKey
(
String
phone
)
{
return
"sms_code:"
+
phone
;
}
...
...
src/main/java/com/infoloop/tianting/service/client/WxMiniProgramHttpClient.java
View file @
99c13c0
...
...
@@ -3,9 +3,11 @@ package com.infoloop.tianting.service.client;
import
com.infoloop.tianting.model.dto.WxUserDto.WxUserOpenIdDto
;
import
com.infoloop.tianting.model.dto.WxUserDto.WxUserPhoneResponseDto
;
import
com.infoloop.tianting.model.dto.WxUserDto.WxUserTokenDto
;
import
com.infoloop.tianting.store.WxAccessTokenStore
;
import
com.infoloop.tianting.utils.JsonUtil
;
import
lombok.RequiredArgsConstructor
;
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.http.HttpEntity
;
...
...
@@ -32,6 +34,8 @@ public class WxMiniProgramHttpClient {
private
final
RestTemplate
restTemplate
;
private
final
WxAccessTokenStore
wxAccessTokenStore
;
@Value
(
MINI_PROGRAM_APP_ID
)
private
String
appId
;
...
...
@@ -40,7 +44,7 @@ public class WxMiniProgramHttpClient {
public
WxUserPhoneResponseDto
getUserPhoneInfoByCode
(
String
code
)
{
try
{
String
accessToken
=
fetchAccessToken
();
String
accessToken
=
fetch
Stable
AccessToken
();
HttpHeaders
headers
=
new
HttpHeaders
();
headers
.
setContentType
(
MediaType
.
APPLICATION_JSON
);
Map
<
String
,
Object
>
jsonDataMap
=
new
HashMap
<>();
...
...
@@ -55,6 +59,11 @@ public class WxMiniProgramHttpClient {
private
String
fetchAccessToken
()
{
log
.
info
(
"Fetching WeChat access token..."
);
final
var
code
=
wxAccessTokenStore
.
getAccessToken
();
if
(
StringUtils
.
isNotEmpty
(
code
))
{
log
.
info
(
"Using cached access token: {}"
,
code
);
return
code
;
}
ResponseEntity
<
String
>
tokenResponse
=
restTemplate
.
getForEntity
(
TOKEN_URL
,
String
.
class
,
appId
,
appSecret
);
if
(!
tokenResponse
.
getStatusCode
().
is2xxSuccessful
()
||
tokenResponse
.
getBody
()
==
null
)
{
log
.
error
(
"Failed to fetch access token: {}"
,
tokenResponse
);
...
...
@@ -62,7 +71,36 @@ public class WxMiniProgramHttpClient {
}
final
var
wxUserTokenDto
=
JsonUtil
.
readJsonAs
(
tokenResponse
.
getBody
(),
WxUserTokenDto
.
class
);
log
.
info
(
"WeChat access token received: {}"
,
wxUserTokenDto
);
return
wxUserTokenDto
.
getAccess_token
();
final
var
accessToken
=
wxUserTokenDto
.
getAccess_token
();
wxAccessTokenStore
.
setAccessToken
(
accessToken
);
return
accessToken
;
}
public
String
fetchStableAccessToken
()
{
log
.
info
(
"Fetching WeChat access token..."
);
final
var
code
=
wxAccessTokenStore
.
getAccessToken
();
if
(
StringUtils
.
isNotEmpty
(
code
))
{
log
.
info
(
"Using cached access token: {}"
,
code
);
return
code
;
}
String
url
=
"https://api.weixin.qq.com/cgi-bin/stable_token"
;
HttpHeaders
headers
=
new
HttpHeaders
();
headers
.
setContentType
(
MediaType
.
APPLICATION_JSON
);
Map
<
String
,
String
>
requestBody
=
new
HashMap
<>();
requestBody
.
put
(
"grant_type"
,
"client_credential"
);
requestBody
.
put
(
"appid"
,
appId
);
requestBody
.
put
(
"secret"
,
appSecret
);
HttpEntity
<
Map
<
String
,
String
>>
request
=
new
HttpEntity
<>(
requestBody
,
headers
);
ResponseEntity
<
String
>
response
=
restTemplate
.
postForEntity
(
url
,
request
,
String
.
class
);
if
(!
response
.
getStatusCode
().
is2xxSuccessful
()
||
response
.
getBody
()
==
null
)
{
log
.
error
(
"Failed to fetch access token: {}"
,
response
);
throw
new
IllegalArgumentException
(
"获取 access_token 失败"
);
}
WxUserTokenDto
tokenDto
=
JsonUtil
.
readJsonAs
(
response
.
getBody
(),
WxUserTokenDto
.
class
);
log
.
info
(
"WeChat access token received: {}"
,
tokenDto
);
final
var
accessToken
=
tokenDto
.
getAccess_token
();
wxAccessTokenStore
.
setAccessToken
(
accessToken
);
return
accessToken
;
}
private
WxUserPhoneResponseDto
fetchPhoneNumber
(
String
accessToken
,
HttpEntity
<
Map
<
String
,
Object
>>
requestEntity
)
{
...
...
src/main/java/com/infoloop/tianting/store/WxAccessTokenStore.java
0 → 100644
View file @
99c13c0
package
com
.
infoloop
.
tianting
.
store
;
import
com.infoloop.tianting.constant.RedisKeyConstants
;
import
io.lettuce.core.SetArgs
;
import
io.lettuce.core.api.sync.RedisCommands
;
public
class
WxAccessTokenStore
{
private
final
RedisCommands
<
String
,
String
>
commands
;
private
final
long
expire
;
public
WxAccessTokenStore
(
final
RedisCommands
<
String
,
String
>
commands
,
final
long
expire
)
{
this
.
commands
=
commands
;
this
.
expire
=
expire
;
}
public
void
setAccessToken
(
final
String
accessToken
)
{
commands
.
set
(
RedisKeyConstants
.
WX_ACCESS_TOKEN
,
accessToken
,
new
SetArgs
().
ex
(
expire
));
}
public
String
getAccessToken
()
{
return
commands
.
get
((
RedisKeyConstants
.
WX_ACCESS_TOKEN
));
}
}
Please
register
or
login
to post a comment