{"record":{"id":"b25fd97408399e84","repo":"justauth/JustAuth","slug":"errcode-b25fd9","errorCode":"${errcode}","errorMessage":"${errmsg}","messagePattern":"\\$\\{errmsg\\}","errorType":"exception","errorClass":"AuthException","httpStatus":null,"severity":"error","filePath":"src/main/java/me/zhyd/oauth/request/AuthWeChatOpenRequest.java","lineNumber":86,"sourceCode":"            .build();\n    }\n\n    @Override\n    public AuthResponse<AuthToken> refresh(AuthToken oldToken) {\n        return AuthResponse.<AuthToken>builder()\n            .code(AuthResponseStatus.SUCCESS.getCode())\n            .data(this.getToken(refreshTokenUrl(oldToken.getRefreshToken())))\n            .build();\n    }\n\n    /**\n     * 检查响应内容是否正确\n     *\n     * @param object 请求响应内容\n     */\n    private void checkResponse(JSONObject object) {\n        if (object.containsKey(\"errcode\")) {\n            throw new AuthException(object.getIntValue(\"errcode\"), object.getString(\"errmsg\"));\n        }\n    }\n\n    /**\n     * 获取token，适用于获取access_token和刷新token\n     *\n     * @param accessTokenUrl 实际请求token的地址\n     * @return token对象\n     */\n    private AuthToken getToken(String accessTokenUrl) {\n        String response = new HttpUtils(config.getHttpConfig()).get(accessTokenUrl).getBody();\n        JSONObject accessTokenObject = JSONObject.parseObject(response);\n\n        this.checkResponse(accessTokenObject);\n\n        return AuthToken.builder()\n            .accessToken(accessTokenObject.getString(\"access_token\"))\n            .refreshToken(accessTokenObject.getString(\"refresh_token\"))","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/justauth/JustAuth/blob/694bbf1b010d93404e3bfb4824d90e9ddfaebebb/src/main/java/me/zhyd/oauth/request/AuthWeChatOpenRequest.java#L68-L104","documentation":"AuthWeChatOpenRequest.checkResponse guards WeChat Open Platform (开放平台) website-app token endpoints: if the response JSON contains `errcode`, JustAuth throws AuthException(errcode, errmsg) — the numeric code on the exception is WeChat's own errcode. It runs on both the access-token fetch and the refresh flow (both routed through getToken).","triggerScenarios":"WeChat Open Platform OAuth failing: invalid code (40029), appsecret mismatch (40125), IP not whitelisted (40164), invalid refresh_token (40030) after the web-app's refresh token was consumed or expired, or component-app style misconfiguration (api unauthorized, 61004).","commonSituations":"Using a website app's appId/secret from the open platform but the server IP was never whitelisted; refresh token already used (WeChat refresh tokens rotate) and the old one replayed from cache; appid under a third-party platform without completing the component authorization.","solutions":["Look up e.getCode() in the WeChat global errcode table and fix the matching config (IP whitelist, secret, code freshness).","For 40030: persist the NEW refresh_token returned by each refresh() call — WeChat open-platform refresh tokens are single-use and rotating.","Add the server egress IP to the open-platform app's web-domain/IP whitelist and verify DNS-level egress (containers/NAT often present a different IP).","Ensure each authorization code is exchanged once, immediately after redirect."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// persist rotated refresh tokens; validate presence before refresh\nif (StringUtils.isEmpty(old.getRefreshToken())) {\n    throw new IllegalStateException(\"WeChat Open: refresh_token missing, re-auth required\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    AuthResponse<AuthToken> r = openRequest.refresh(old);\n} catch (AuthException e) {\n    if (e.getCode() == 40030 || e.getCode() == 40029) {\n        redirect(openRequest.authorize(newState())); // refresh/code dead → re-consent\n    } else if (e.getCode() == 40164) {\n        throw new ConfigurationException(\"whitelist egress IP in WeChat Open console\", e);\n    } else throw e;\n}","preventionTips":["Store the refresh_token returned by every refresh call — WeChat rotates them.","Whitelist all server IPs in the open-platform website-app settings.","Treat 40030 as an unrecoverable signal to re-authenticate, not to retry."],"tags":["justauth","wechat-open","errcode","refresh-token","ip-whitelist"],"backgroundTag":null,"analyzedSha":"694bbf1b010d93404e3bfb4824d90e9ddfaebebb","analyzedAt":"2026-08-14T15:16:59.945Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}