{"record":{"id":"c00319f09c017700","repo":"binarywang/WxJava","slug":"secret-c00319","errorCode":null,"errorMessage":"通讯录同步secret未配置","messagePattern":"通讯录同步secret未配置","errorType":"validation","errorClass":"WxErrorException","httpStatus":null,"severity":"error","filePath":"weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceApacheHttpClientImpl.java","lineNumber":94,"sourceCode":"  }\n\n  @Override\n  public String getContactAccessToken(boolean forceRefresh) throws WxErrorException {\n    if (!this.configStorage.isContactAccessTokenExpired() && !forceRefresh) {\n      return this.configStorage.getContactAccessToken();\n    }\n\n    Lock lock = this.configStorage.getContactAccessTokenLock();\n    lock.lock();\n    try {\n      // 拿到锁之后，再次判断一下最新的token是否过期，避免重刷\n      if (!this.configStorage.isContactAccessTokenExpired() && !forceRefresh) {\n        return this.configStorage.getContactAccessToken();\n      }\n      // 使用通讯录同步secret获取access_token\n      String contactSecret = this.configStorage.getContactSecret();\n      if (contactSecret == null || contactSecret.trim().isEmpty()) {\n        throw new WxErrorException(\"通讯录同步secret未配置\");\n      }\n      String url = String.format(this.configStorage.getApiUrl(WxCpApiPathConsts.GET_TOKEN),\n        this.configStorage.getCorpId(), contactSecret);\n\n      try {\n        HttpGet httpGet = new HttpGet(url);\n        if (this.httpProxy != null) {\n          RequestConfig config = RequestConfig.custom()\n            .setProxy(this.httpProxy).build();\n          httpGet.setConfig(config);\n        }\n        String resultContent = getRequestHttpClient().execute(httpGet, ApacheBasicResponseHandler.INSTANCE);\n        WxError error = WxError.fromJson(resultContent, WxType.CP);\n        if (error.getErrorCode() != 0) {\n          throw new WxErrorException(error);\n        }\n\n        WxAccessToken accessToken = WxAccessToken.fromJson(resultContent);","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/binarywang/WxJava/blob/1c43293a3c2c9d7e91304b6d037fb017f680d0c6/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceApacheHttpClientImpl.java#L76-L112","documentation":"Thrown (as checked WxErrorException) by getContactAccessToken() in the Apache HttpClient implementation when the contact-sync secret (通讯录同步secret) is null or blank. This secret is required to obtain a separate access_token for contact-sync API calls, distinct from the main corp secret.","triggerScenarios":"Calling any method that triggers getContactAccessToken(true) — typically contact/department/user sync operations — when configStorage.getContactSecret() returns null or an empty/whitespace string.","commonSituations":"The WxCpConfigStorage was initialized without calling setContactSecret(); the secret was set from an environment variable that is not defined in the current deployment; the secret was cleared during a config refresh; using a config storage that does not persist the contact secret across restarts.","solutions":["Set the contact secret via configStorage.setContactSecret(\"your-contact-sync-secret\") during initialization","In Spring Boot starter, set wx.cp.contact-secret in application.yml","Ensure the secret value comes from a reliable source (env var, config center) that is present in all environments","Verify the secret is the 通讯录同步 secret from the WeChat Work admin console, not the main application secret"],"exampleFix":"// before\nWxCpConfigStorage config = new WxCpDefaultConfigImpl();\nconfig.setCorpId(\"corp123\");\nconfig.setCorpSecret(\"app-secret\");\n// contactSecret never set → getContactAccessToken fails\n\n// after\nWxCpDefaultConfigImpl config = new WxCpDefaultConfigImpl();\nconfig.setCorpId(\"corp123\");\nconfig.setCorpSecret(\"app-secret\");\nconfig.setContactSecret(System.getenv(\"WX_CP_CONTACT_SECRET\"));","handlingStrategy":"validation","validationCode":"// Validate contact secret is configured at startup\nString contactSecret = configStorage.getContactSecret();\nif (StringUtils.isBlank(contactSecret)) {\n  throw new IllegalStateException(\"启动检查失败：通讯录同步 secret 未配置，请在企业微信管理后台获取并设置 contactSecret\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Set all three secrets (corpSecret, contactSecret, msgAuditSecret) during application initialization","Use environment variables or a config center, not hardcoded values","Add a startup health check that validates all required secrets are non-blank","For Spring Boot starter, configure wx.cp.contact-secret in application.yml"],"tags":["wechat-cp","config","contact-sync","access-token","secret","apache-httpclient"],"backgroundTag":null,"analyzedSha":"1c43293a3c2c9d7e91304b6d037fb017f680d0c6","analyzedAt":"2026-08-14T02:29:11.060Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}