收藏
回答

我在开发微信小程序拉取手机号进行登录时,AccessToken动不动就会过期,这个该怎么解决啊?

如下是我去获取手机号的代码,最主要的就是动不动就会提示“获取微信手机号接口调用失败”,然后微信那边返回的错误json就是
【{"errcode":40001,"errmsg":"invalid credential, access_token is invalid or not latest, could get access_token by getStableAccessToken, more details at https://mmbizurl.cn/s/JtxxFh33r rid: 68cb7fef-5fe44b85-267f8413"}】

我是把AccessToken存放在Redis里面的,而且redis的过期时间比AccessToken本身要少。

我设置的loginType字段是为了区分是什么操作系统进行登录,比如:ios、Windows、android等,不知道有没有这个必要。(主要是因为之前没加这个loginType,
也会出现AccessToken过期的问题,我以为是电脑端和手机端导致的token不兼容问题,就加上了这么多type区分下),但是现在问题还是一样的,我用多个手机进行多次登录,和退出登录操作,几分钟内就会出现在拉取手机号进行登录时,就会出现AccessToken过期的问题
请大佬帮忙看看,给个解决方案呢,谢谢!

public String getPhoneNumber(String phoneCode, String loginType) {
    String accessToken = getMiniProgramAccessToken(appId, appSecret, loginType);
    String url = GET_PHONE_NUMBER_URL + accessToken;
    Map<String, String> requestBody = new HashMap<>();
    requestBody.put("code", phoneCode);

    String responseObj = httpClientUtil.doPost(url, JSONUtil.toJsonStr(requestBody), null);
    JSONObject phoneInfoObj = JSONUtil.parseObj(responseObj);
    if (phoneInfoObj.getInt("errcode") == 0) {
        JSONObject phoneInfo = phoneInfoObj.getJSONObject("phone_info");
        return phoneInfo.getStr("purePhoneNumber");
    } else {
        log.error("获取手机号失败: {}, accessToken:{}", phoneInfoObj, accessToken);
    }
    throw new TcmCommonException("获取微信手机号接口调用失败");
}
public String getMiniProgramAccessToken(String appId, String appSecret, String loginType) {
    return getAccessTokenFromWechat(appId, appSecret, RedisCacheConstants.WECHAT_ACCESS_TOKEN_KEY + loginType);
}
private String getAccessTokenFromWechat(String appId, String appSecret, String redisKey) {
    WechatAccessTokenCache accessTokenCache = redisCacheUtil.getCacheObject(redisKey);
    if (accessTokenCache != null && StringUtils.isNotBlank(accessTokenCache.getAccessToken())) {
        return accessTokenCache.getAccessToken();
    }

    String url = String.format(TOKEN_URL, appSecret, appId);
    String responseStr = httpClientUtil.doGet(url, null);

    JSONObject jsonObject = JSONUtil.parseObj(responseStr);

    if (jsonObject.containsKey("errcode")) {
        throw new TcmCommonException("获取微信 access_token 失败,errcode="
                + jsonObject.getInt("errcode") + ", errmsg=" + jsonObject.getStr("errmsg"));
    }

    String accessToken = jsonObject.getStr("access_token");
    int tokenExpireTime = jsonObject.getInt("expires_in");
    WechatAccessTokenCache tokenCache = new WechatAccessTokenCache();
    tokenCache.setAccessToken(accessToken);
    tokenCache.setExpireTime(System.currentTimeMillis() + tokenExpireTime * 1000L);
    log.info("获取微信access_token成功,access_token:[{}], redisKey:[{}]", accessToken, redisKey);
    redisCacheUtil.setCacheObject(redisKey, tokenCache, tokenExpireTime - 300, TimeUnit.SECONDS);

    return accessToken;
}
回答关注问题邀请回答
收藏

2 个回答

  • 第三方平台小助手
    第三方平台小助手
    2025-09-18

    你好,报错40001,请开发者仔细排查代码,检查拼接的token参数,是否有其他刷新token机制导致之前获取的旧Token过期

    2025-09-18
    有用
    回复
  • 拾忆
    拾忆
    2025-09-18

    token需要存在自己的服务器上,每次获取的token有效期是2小时,如果你所有请求每次都请求token自然会导致失效,token只有你自己多次请求的情况下上一个才会失效,自己排查程序哪里有问题。

    也可以使用稳定版接口,具体规则参考文档:https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-access-token/getStableAccessToken.html

    2025-09-18
    有用
    回复 6
    • 荣幸之至
      荣幸之至
      2025-09-18
      我不会每次都去请求token,我是存在redis里面的。只是根据不同的操作端会再次去请求token。比如:我用iphone去操作小程序登录之后,拿到了token,然后我又用android手机去操作小程序登录,这时我就会再次去请求拿token。   但问题是:我在根据不同端去拿token之前,我的流程就如你所说那样,没有分端,就是同一个token应付所有的手机。但还是会动不动就过期。   随便请问下,电脑端的小程序和手机端的,他们的AccessToken是能用同一个吗,还是要区分一下的。
      2025-09-18
      回复
    • 拾忆
      拾忆
      2025-09-18回复荣幸之至
      token是针对服务端的,接口不区分你是什么端调用接口。
      2025-09-18
      回复
    • 荣幸之至
      荣幸之至
      2025-09-18回复拾忆
      那对于公众号去获取token和小程序去获取token,这两种情况,会出现导致上一个失效的情况吗。因为这两种对应的使用场景和appid、secret都不一样。但是我现在就有用到这两种场景。
      2025-09-18
      回复
    • 荣幸之至
      荣幸之至
      2025-09-18
      图上是我截图服务器的问题,这个是我现在出现的问题,我已经没有区分任何type了。我就是用了三个手机在反复操作,小程序登录和退出登录(我在刚刚修改完代码之后,第一次登录拿到的token,我就把它存放到了redis了),期间的这些操作,都没有去再次获取token 的操作,因为我在去获取token的时候,都是打印了日志的,所以能确定没有再次获取token。 这是为啥呀。大佬 请帮我看看呢 感谢感谢
      2025-09-18
      回复
    • 拾忆
      拾忆
      2025-09-18回复荣幸之至
      每个不同appid获取到的token都是独立唯一的,出现“invalid credential, access_token is invalid or not latest”基本都是自己服务端多次调用接口导致的,只能自己排查代码,如果排查不出来就重置secret。
      2025-09-18
      回复
    查看更多(1)
登录 后发表内容