binarywang/WxJava · error · WxErrorException
通讯录同步secret未配置
Error message
通讯录同步secret未配置
What it means
Thrown (as checked WxErrorException) by getContactAccessToken() in the Jodd HTTP implementation when the contact-sync secret is null or blank. Identical validation logic to the other service implementations, specific to the Jodd HTTP client variant.
Source
Thrown at weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceJoddHttpImpl.java:84
}
@Override
public String getContactAccessToken(boolean forceRefresh) throws WxErrorException {
if (!this.configStorage.isContactAccessTokenExpired() && !forceRefresh) {
return this.configStorage.getContactAccessToken();
}
Lock lock = this.configStorage.getContactAccessTokenLock();
lock.lock();
try {
// 拿到锁之后,再次判断一下最新的token是否过期,避免重刷
if (!this.configStorage.isContactAccessTokenExpired() && !forceRefresh) {
return this.configStorage.getContactAccessToken();
}
// 使用通讯录同步secret获取access_token
String contactSecret = this.configStorage.getContactSecret();
if (contactSecret == null || contactSecret.trim().isEmpty()) {
throw new WxErrorException("通讯录同步secret未配置");
}
HttpRequest request = HttpRequest.get(String.format(this.configStorage.getApiUrl(WxCpApiPathConsts.GET_TOKEN),
this.configStorage.getCorpId(), contactSecret));
if (this.httpProxy != null) {
httpClient.useProxy(this.httpProxy);
}
request.withConnectionProvider(httpClient);
HttpResponse response = request.send();
String resultContent = response.bodyText();
WxError error = WxError.fromJson(resultContent, WxType.CP);
if (error.getErrorCode() != 0) {
throw new WxErrorException(error);
}
WxAccessToken accessToken = WxAccessToken.fromJson(resultContent);
this.configStorage.updateContactAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn());
} finally {
lock.unlock();View on GitHub (pinned to 1c43293a3c)
Solutions
- Set the contact secret via configStorage.setContactSecret() regardless of which HTTP client implementation you use
- Ensure wx.cp.contact-secret is in application.yml for Spring Boot with the Jodd implementation
- Centralize secret configuration so all HTTP client variants share the same config source
Example fix
// before — Jodd impl, contact secret missing
WxCpServiceJoddHttpImpl service = new WxCpServiceJoddHttpImpl();
service.setWxCpConfigStorage(config); // config.contactSecret == null
// after
config.setContactSecret(System.getenv("WX_CP_CONTACT_SECRET"));
service.setWxCpConfigStorage(config); Defensive patterns
Strategy: validation
Validate before calling
// Validate contact secret for Jodd impl
String contactSecret = configStorage.getContactSecret();
if (StringUtils.isBlank(contactSecret)) {
throw new IllegalStateException("通讯录同步 secret 未配置");
} Prevention
- Secret configuration must be set regardless of HTTP client implementation (Jodd, Apache, HttpComponents, default)
- Centralize config setup so the secret is always populated
- For Spring Boot, use wx.cp.contact-secret
When it happens
Trigger: Any contact-sync API call via WxCpServiceJoddHttpImpl when configStorage.getContactSecret() returns null or whitespace.
Common situations: Switched to the Jodd HTTP client implementation without copying the contact secret into the config; env var missing in the deployment that uses Jodd; config storage that does not persist the contact secret.
Related errors
AI-assisted analysis of binarywang/WxJava@1c43293a3c (2026-08-14).
Data as JSON: /api/errors/728dbb4e711a69da.
Report an issue: GitHub.