微信公众号的Stable Access token是调用各类接口的核心凭证,当token过期时,所有依赖该凭证的接口请求都会返回错误,影响业务正常运行。下面我们来详细讲解如何解决token过期的问题。

Stable Access token的过期机制
微信官方提供的Stable Access token有效期为7200秒,也就是2小时,到期后自动失效。和普通的access_token不同,Stable Access token在有效期内重复请求不会刷新过期时间,只有等到过期后重新获取才会得到新的token。
token过期的常见原因
- 没有做token缓存,每次调用接口都重新获取,导致频繁请求超过微信接口调用限制
- 缓存过期时间设置错误,没有按照7200秒的有效期设置,提前失效
- 服务重启后缓存丢失,没有持久化存储token,重启后拿到旧的过期token
- 多实例部署时,不同实例各自获取token,出现token覆盖或者不同步的情况
完整的解决方案
1. 使用缓存存储token
不要每次调用接口都重新请求token,应该把获取到的token存入缓存,设置合理的过期时间。这里以Redis缓存为例,示例代码如下:
import redis
import requests
import time
# 连接Redis
redis_client = redis.Redis(host='127.0.0.1', port=6379, db=0)
# 微信配置
APPID = "你的公众号APPID"
APPSECRET = "你的公众号APPSECRET"
TOKEN_KEY = "wechat_stable_access_token"
def get_stable_access_token():
# 先从缓存获取token
token = redis_client.get(TOKEN_KEY)
if token:
return token.decode('utf-8')
# 缓存没有则请求微信接口获取
url = f"https://api.weixin.qq.com/cgi-bin/stable_token"
data = {
"grant_type": "client_credential",
"appid": APPID,
"secret": APPSECRET,
"force_refresh": False # 不强制刷新,避免频繁更新
}
response = requests.post(url, json=data)
result = response.json()
if "access_token" in result:
access_token = result["access_token"]
# 存入Redis,设置过期时间为7000秒,提前200秒刷新避免临界问题
redis_client.setex(TOKEN_KEY, 7000, access_token)
return access_token
else:
raise Exception(f"获取token失败:{result.get('errmsg')}")2. 实现定时刷新逻辑
为了避免token过期影响业务,可以在token过期前主动刷新。可以写一个定时任务,每隔7000秒执行一次获取token的逻辑,覆盖旧的缓存。如果是使用Linux服务器,也可以用crontab定时执行刷新脚本,示例定时任务代码如下:
import schedule
import time
def refresh_token_task():
try:
# 强制刷新获取新token
url = "https://api.weixin.qq.com/cgi-bin/stable_token"
data = {
"grant_type": "client_credential",
"appid": APPID,
"secret": APPSECRET,
"force_refresh": True
}
response = requests.post(url, json=data)
result = response.json()
if "access_token" in result:
new_token = result["access_token"]
redis_client.setex(TOKEN_KEY, 7000, new_token)
print(f"token刷新成功,新token:{new_token}")
else:
print(f"token刷新失败:{result.get('errmsg')}")
except Exception as e:
print(f"刷新任务执行异常:{str(e)}")
# 每隔7000秒执行一次刷新任务
schedule.every(7000).seconds.do(refresh_token_task)
if __name__ == "__main__":
while True:
schedule.run_pending()
time.sleep(1)3. 多实例部署的同步处理
如果服务是多实例部署,需要保证所有实例共享同一个token,避免各自获取导致冲突。这时候可以使用分布式锁,在获取token的时候加锁,同一时间只有一个实例可以获取新token,其他实例等待缓存更新后直接读取。Redis分布式锁的实现示例如下:
def get_token_with_lock():
lock_key = "wechat_token_lock"
# 尝试获取分布式锁,过期时间10秒,避免死锁
if redis_client.set(lock_key, 1, nx=True, ex=10):
try:
# 获取锁成功,执行获取token逻辑
token = get_stable_access_token()
return token
finally:
# 释放锁
redis_client.delete(lock_key)
else:
# 没获取到锁,等待100毫秒后重试读取缓存
time.sleep(0.1)
return get_token_with_lock()4. 接口调用时的异常处理
即使做了缓存和刷新,也可能出现token刚好过期的临界情况,所以调用接口的时候需要捕获token过期的错误码,触发重新获取token的逻辑。微信返回的错误码40001就是token无效或者过期,处理示例如下:
def call_wechat_api(url, params):
params["access_token"] = get_stable_access_token()
response = requests.get(url, params=params)
result = response.json()
# 如果返回token过期错误,重新获取token后重试
if result.get("errcode") == 40001:
# 删除旧缓存,强制获取新token
redis_client.delete(TOKEN_KEY)
params["access_token"] = get_stable_access_token()
response = requests.get(url, params=params)
result = response.json()
return result注意事项
不要频繁调用获取Stable Access token的接口,微信有接口调用频率限制,超出限制会被封禁。另外缓存的过期时间不要设置成7200秒整,建议预留200秒左右的缓冲时间,避免刚好到过期时间的时候接口请求失败。如果是使用数据库存储token,要注意存储的字段长度足够,避免token被截断导致失效。
微信公众号Stable_Access_tokenaccess_token过期缓存机制定时刷新修改时间:2026-05-31 05:01:11