{"record":{"id":"dd461c35d684e1df","repo":"binarywang/WxJava","slug":"webhookkey","errorCode":null,"errorMessage":"请先设置WebhookKey","messagePattern":"请先设置WebhookKey","errorType":"validation","errorClass":"WxErrorException","httpStatus":null,"severity":"error","filePath":"weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpGroupRobotServiceImpl.java","lineNumber":30,"sourceCode":"\nimport java.util.List;\n\nimport static me.chanjar.weixin.cp.constant.WxCpConsts.GroupRobotMsgType;\n\n/**\n * 企业微信群机器人消息发送api 实现\n *\n * @author yr  created on  2020-08-20\n */\n@RequiredArgsConstructor\npublic class WxCpGroupRobotServiceImpl implements WxCpGroupRobotService {\n  private final WxCpService cpService;\n\n  private String getWebhookUrl() throws WxErrorException {\n    WxCpConfigStorage wxCpConfigStorage = this.cpService.getWxCpConfigStorage();\n    final String webhookKey = wxCpConfigStorage.getWebhookKey();\n    if (StringUtils.isEmpty(webhookKey)) {\n      throw new WxErrorException(\"请先设置WebhookKey\");\n    }\n    return wxCpConfigStorage.getApiUrl(WxCpApiPathConsts.WEBHOOK_SEND) + webhookKey;\n  }\n\n  @Override\n  public void sendText(String content, List<String> mentionedList, List<String> mobileList) throws WxErrorException {\n    this.sendText(this.getWebhookUrl(), content, mentionedList, mobileList);\n  }\n\n  @Override\n  public void sendMarkdown(String content) throws WxErrorException {\n    this.sendMarkdown(this.getWebhookUrl(), content);\n  }\n\n  @Override\n  public void sendMarkdownV2(String content) throws WxErrorException {\n    this.sendMarkdownV2(this.getWebhookUrl(), content);\n  }","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/binarywang/WxJava/blob/1c43293a3c2c9d7e91304b6d037fb017f680d0c6/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpGroupRobotServiceImpl.java#L12-L48","documentation":"Thrown as WxErrorException (checked) by getWebhookUrl() in WxCpGroupRobotServiceImpl when the webhookKey is empty or not set in WxCpConfigStorage. The webhook key is the unique token appended to the group robot webhook URL; without it the robot endpoint cannot be constructed. This fires before any HTTP request on every send method (sendText, sendMarkdown, etc.) that relies on the default webhook URL.","triggerScenarios":"Calling any group robot send method (sendText, sendMarkdown, sendImage, sendNews, sendFile) without having set the webhook key on the config storage. The key is typically extracted from the webhook URL provided in WeCom group chat robot settings.","commonSituations":"Developer initializes WxCpService with corpId/secret but forgets to call configStorage.setWebhookKey(key) or setWebhookKey on the InMemoryConfigStorage. Or they confuse the app secret with the webhook key.","solutions":["Extract the webhook key from the full webhook URL (the part after 'key=' in https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=XXX) and set it: ((WxCpDefaultConfigImpl) configStorage).setWebhookKey(\"XXX\").","If you already have the full webhook URL, use the overloaded send methods that accept a url parameter directly, bypassing getWebhookUrl().","Verify the key is set before sending: if (StringUtils.isEmpty(configStorage.getWebhookKey())) set it first."],"exampleFix":"// before\nWxCpDefaultConfigImpl config = new WxCpDefaultConfigImpl();\nconfig.setCorpId(\"corpId\");\nconfig.setCorpSecret(\"secret\");\n// webhook key never set\ncpService.getGroupRobotService().sendText(\"hello\", null, null); // throws\n\n// after\nconfig.setWebhookKey(\"12345678-abcd-efgh-ijkl-1234567890ab\");\ncpService.getGroupRobotService().sendText(\"hello\", null, null);","handlingStrategy":"validation","validationCode":"if (StringUtils.isEmpty(cpService.getWxCpConfigStorage().getWebhookKey())) {\n    throw new IllegalStateException(\"WebhookKey is not configured; set it via configStorage.setWebhookKey(key)\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    cpService.getGroupRobotService().sendText(content, mentionedList, mobileList);\n} catch (WxErrorException e) {\n    if (e.getMessage().contains(\"WebhookKey\")) {\n        // configure webhook key and retry\n    }\n    throw e;\n}","preventionTips":["Extract the webhook key from the full webhook URL and set it on config storage at application startup.","Use the overloaded send methods that accept a full URL if you prefer not to use config storage.","Add a startup health check that verifies webhookKey is non-empty before the app accepts requests."],"tags":["weixin-cp","group-robot","config","webhook","precondition"],"backgroundTag":null,"analyzedSha":"1c43293a3c2c9d7e91304b6d037fb017f680d0c6","analyzedAt":"2026-08-14T02:29:11.060Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}