“errcode“:40164,“errmsg“:“invalid ip ...微信公众号开发调用失败的解决办法

问题概述

关于这个问题,博主是在进行微信公众号平台开发的过程中遇到的,

微信公众号平台的前后端代码开发完成后,在联调接口调用:

“ https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s

获取微信的access_token时,回调异常信息:“ errcode“:40164,“errmsg“:“invalid ip ...

如下图:

解决办法

根据回调code,查询码表得知,是因为:调用接口的 IP 地址不在白名单中,请在接口 IP 白名单中进行设置

解决步骤:

登录“ 微信公众号平台 ” > 首页 > 设置与开发 > 基本设置 > 公众号开发信息  > IP白名单 > 配置,

如下图:

期间需要公众号所有者,进行扫码授权即可完成绑定,如果是多个IP的话,换行写即可,绑定成功后如下图:

说明:
1、注意请求域名IP的正确,且IP地址已经完成备案的,如果不知道IP是多少,可以通过DOS窗口中ping指令获得当前域名的IP;
2、云虚拟主机,例如:BAE、SAE,需要注意,出/入的IP是不一样的,就不能用ping指令来获取其IP了,外部访问的IP和服务器请求的出去的IP是不一样。这个就需要从云虚拟主机的供应商处或者公司内部的运营团队处获取IP了;
3、如果是四层SLB(虚拟IP+端口>IP)或者七层SLB(URL>IP)架构的应用服务,则需要整个四层/七层SLB中的IP都加入到IP百名单中;

加入白名单后,就可以正常的请求了,如下图:

参考:
微信开放社区
微信官方文档-公众号-40164
微信官方文档-公众号-40013
微信公众平台技术文档-WIKI


好了,关于 “errcode“:40164,“errmsg“:“invalid ip ...微信公众号开发调用失败的解决办法  就写到这儿了,如果还有什么疑问或遇到什么问题欢迎扫码提问,也可以给我留言哦,我会一一详细的解答的。 
歇后语:“ 共同学习,共同进步 ”,也希望大家多多关注CSND的IT社区。


作       者:华    仔
联系作者:who.seek.me@java98k.vip
来        源:优快云 (Chinese Software Developer Network)
原        文:https://blog.youkuaiyun.com/Hello_World_QWP/article/details/125877778
版权声明:本文为博主原创文章,请在转载时务必注明博文出处!

<think> 针对用户的问题:不使用云函数解决微信小程序中遇到的 `errcode 40001 invalid credential access_token is invalid or not latest` 错误,我们可以从以下几个方面进行解决: ### 问题原因分析 根据引用内容[^1][^2][^3]: 1. `access_token` 过期(微信默认有效期为2小时) 2. 多个服务器或服务同时刷新 `access_token` 导致旧token被覆盖 3. 没有正确存储和复用 `access_token` 4. 使用了错误的 `appid` 或 `appsecret`(但用户已排除此情况) ### 解决方案(纯前端实现) 由于微信官方要求 `access_token` 必须由服务器获取(避免泄露 `appsecret`),纯前端无法直接调用获取 `access_token` 的接口。但我们可以通过以下方式绕开云函数: #### 方法1:使用微信云托管/云开发HTTP服务 在微信云开发中开启HTTP访问服务,替代传统服务器: ```javascript // 获取access_token async function getAccessToken() { const res = await uni.request({ url: 'https://your-service-xxx.service.tcloudbase.com/token', // 云托管服务地址 method: 'GET' }); return res.data.access_token; } ``` #### 方法2:利用本地缓存+定时刷新 通过 `uni.setStorageSync` 存储 `access_token` 并记录时间: ```javascript // 统一获取access_token的方法 async function getValidAccessToken() { const cache = uni.getStorageSync('access_token_cache'); // 检查缓存是否存在且未过期(假设缓存1小时50分钟) if (cache && Date.now() - cache.timestamp < 110 * 60 * 1000) { return cache.access_token; } // 通过自有后端或云HTTP服务获取新token const newToken = await fetchNewTokenFromServer(); // 更新缓存 uni.setStorageSync('access_token_cache', { access_token: newToken, timestamp: Date.now() }); return newToken; } // 发送订阅消息时使用 async function sendSubscribeMessage() { try { const access_token = await getValidAccessToken(); // 调用微信API... } catch (e) { // 处理错误 } } ``` ### 错误处理机制 根据引用[^3]的建议: 1. **重试机制**:当返回40001错误时,强制刷新 `access_token` 并重试 ```javascript async function sendWithRetry(payload) { let retry = 0; while (retry < 2) { // 最多重试1次 try { const access_token = await getValidAccessToken(); const res = await wx.request({ url: `https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=${access_token}`, method: 'POST', data: payload }); // 检查是否token失效 if (res.data.errcode === 40001) { throw new Error('invalid token'); } return res; } catch (e) { // 清除缓存并重试 uni.removeStorageSync('access_token_cache'); retry++; } } throw new Error('发送失败'); } ``` ### 关键注意事项 1. **避免多服务冲突**(引用[^3]) - 确保所有服务使用同一个缓存源(如redis) - 在纯前端环境中,使用 `uni.setStorage` 共享缓存 2. **时间同步问题** ```javascript // 获取token时记录过期时间(微信返回7200秒) const expiresIn = res.data.expires_in * 1000; // 转为毫秒 const timestamp = Date.now(); uni.setStorageSync('access_token_cache', { access_token: res.data.access_token, expireTime: timestamp + expiresIn - 300000 // 提前5分钟过期 }); ``` 3. **URL拼接问题**(引用[^5]) 避免错误拼接: ```javascript // 错误示例(access_token参数未正确插入) const url = `https://...?access_token=${access_token}`; // 正确写法 ``` ### 最终实现流程图 ```mermaid graph TD A[发送消息] --> B{本地有有效token?} B -->|是| C[使用本地token发送] B -->|否| D[请求服务器获取新token] D --> E[存储token并记录时间] E --> C C --> F{返回40001?} F -->|是| G[清除本地token] G --> D F -->|否| H[发送成功] ``` > **重要提示**:真正的生产环境仍建议使用后端服务器管理 `access_token`,前端只通过接口调用业务逻辑[^3]。 §§相关问题§§ 1. 微信小程序中如何安全地管理敏感信息如appSecret? 2. 如何处理多个小程序共用同一后台服务时的token冲突? 3. 微信订阅消息发送失败有哪些常见错误代码? 4. 如何优化前端token管理减少40001错误发生频率? </think> 针对微信小程序开发中遇到的 `errcode 40001 invalid credential access_token is invalid or not latest` 错误,在不使用云函数的情况下,可通过以下方案解决: ### 问题根本原因分析 1. **access_token 过期**:微信 access_token 有效期为 2 小时(7200秒),超时即失效[^1][^2] 2. **多服务冲突**:多个服务器或服务同时刷新 token,导致旧 token 被覆盖[^3] 3. **缓存机制缺失**:未实现 token 的缓存和复用机制 4. **时间不同步**:本地时间与微信服务器时间不同步 ### 纯前端解决方案(无需云函数) #### 1. 实现本地缓存与自动刷新机制 ```javascript // utils/tokenManager.js const TOKEN_KEY = 'wx_access_token'; const EXPIRE_KEY = 'wx_token_expire'; export default { // 获取有效token async getValidToken() { const now = Date.now(); const expireTime = uni.getStorageSync(EXPIRE_KEY) || 0; // 如果token未过期且存在,直接返回 if (now < expireTime && uni.getStorageSync(TOKEN_KEY)) { return uni.getStorageSync(TOKEN_KEY); } // 重新获取token return this.refreshToken(); }, // 刷新token async refreshToken() { try { // 通过安全代理获取token(见方案2) const res = await uni.request({ url: 'https://your-proxy-domain.com/api/get-token', method: 'GET' }); if (res.statusCode === 200 && res.data.access_token) { const { access_token, expires_in } = res.data; const expireTime = Date.now() + (expires_in - 300) * 1000; // 提前5分钟过期 // 存储token和过期时间 uni.setStorageSync(TOKEN_KEY, access_token); uni.setStorageSync(EXPIRE_KEY, expireTime); return access_token; } } catch (e) { console.error('刷新token失败:', e); throw new Error('TOKEN_REFRESH_FAILED'); } } } ``` #### 2. 使用 Nginx 反向代理保护 AppSecret 在自有服务器配置 Nginx 代理,避免前端暴露 AppSecret: ```nginx # Nginx 配置 (nginx.conf) server { listen 80; server_name your-proxy-domain.com; location /api/get-token { # 转发到微信API,并隐藏AppSecret proxy_pass https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=YOUR_APPID&secret=YOUR_APPSECRET; proxy_set_header Host api.weixin.qq.com; proxy_hide_header Set-Cookie; } } ``` #### 3. 接口调用时自动处理 token 失效 ```javascript // 发送订阅消息时 async sendMessage() { try { const tokenManager = require('@/utils/tokenManager'); const access_token = await tokenManager.getValidToken(); const res = await uni.request({ url: `https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=${access_token}`, method: 'POST', data: { touser: 'USER_OPENID', template_id: 'TEMPLATE_ID', // ...其他参数 } }); // 处理40001错误自动重试 if (res.data.errcode === 40001) { console.log('Token过期,强制刷新后重试...'); uni.removeStorageSync(TOKEN_KEY); // 清除失效token return this.sendMessage(); // 递归重试 } return res; } catch (e) { console.error('消息发送失败:', e); } } ``` ### 关键优化点 1. **双缓冲机制**: ```javascript // 存储两个token互为备份 const tokens = { current: { token: '', expire: 0 }, backup: { token: '', expire: 0 } }; ``` 2. **时间同步方案**: ```javascript // 获取微信服务器时间 async syncWechatTime() { const res = await uni.request('https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential'); const wechatTime = new Date(res.header.Date).getTime(); const timeDiff = Date.now() - wechatTime; uni.setStorageSync('time_diff', timeDiff); } ``` 3. **错误重试策略**: ```javascript let retryCount = 0; async function requestWithRetry() { try { // ...业务请求 } catch (e) { if (e.errcode === 40001 && retryCount < 2) { retryCount++; await tokenManager.refreshToken(); return requestWithRetry(); } } } ``` ### 方案优势对比 | 方案 | 安全性 | 实现复杂度 | 维护成本 | |------|--------|------------|----------| | **本地缓存+代理** | ★★★★☆ | ★★☆☆☆ | ★★☆☆☆ | | 纯前端存储token | ★☆☆☆☆ | ★☆☆☆☆ | ★★★☆☆ | | 每次请求刷新token | ★★★★☆ | ★★★★☆ | ★★☆☆☆ | > **重要提示**:生产环境必须通过自有服务器中转获取 token,直接在前端存储 `AppSecret` 会导致严重安全风险[^3][^4]。 ### 常见错误排查 1. **URL拼接错误**(引用[^5]): ```javascript // 错误示例:access_token未正确插入 const url = `https://api.weixin.qq.com/send?access_token=?`; // 正确写法 const url = `https://api.weixin.qq.com/send?access_token=${token}`; ``` 2. **多环境冲突**: - 开发/生产环境使用不同的 AppID - 各环境独立 token 缓存(通过 `uni.setStorageSync` 区分)
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TechBro华仔

日拱一卒无有尽,功不唐捐终入海

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值