{"record":{"id":"13c3f11c454f5352","repo":"w7corp/easywechat","slug":"the-token-is-required-to-validate-the-request-sign","errorCode":null,"errorMessage":"The token is required to validate the request signature, please pass it to the server or configure the `token` of the application.","messagePattern":"The token is required to validate the request signature, please pass it to the server or configure the `token` of the application\\.","errorType":"exception","errorClass":"InvalidConfigException","httpStatus":null,"severity":"error","filePath":"src/OfficialAccount/Server.php","lineNumber":187,"sourceCode":"    protected function validatePlainRequest(array $query): void\n    {\n        $this->validatePlainSignature(\n            token: $this->getToken(),\n            signature: $this->getQueryValue($query, 'signature'),\n            timestamp: $this->getQueryValue($query, 'timestamp'),\n            nonce: $this->getQueryValue($query, 'nonce')\n        );\n    }\n\n    /**\n     * @throws InvalidConfigException\n     */\n    protected function getToken(): string\n    {\n        $token = $this->token ?? $this->encryptor?->getToken();\n\n        if (empty($token)) {\n            throw new InvalidConfigException(\n                'The token is required to validate the request signature, '\n                .'please pass it to the server or configure the `token` of the application.'\n            );\n        }\n\n        return $token;\n    }\n\n    /**\n     * @param  array<string,mixed>  $query\n     */\n    protected function decryptIncomingMessage(\\EasyWeChat\\Kernel\\Message $message, array $query): \\EasyWeChat\\Kernel\\Message\n    {\n        if (! $this->encryptor) {\n            return $message;\n        }\n\n        $signature = $this->getQueryValue($query, 'msg_signature');","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/w7corp/easywechat/blob/f0cf0a8b8361417ed683b8246d0ecbaf0aafcaa8/src/OfficialAccount/Server.php#L169-L205","documentation":"Server::getToken() resolves the callback token as the explicitly passed constructor token or falls back to the encryptor's token; when both are empty it throws InvalidConfigException because signature validation of inbound requests (signature/msg_signature) is impossible without it. Built from the Application, the token comes from the 'token' config key, so token-less API-only setups hit this on the first callback.","triggerScenarios":"$app->getServer()->serve() (or echostr verification via validatePlainRequest()) on an Application whose config lacks 'token'; a manually constructed Server given neither token nor encryptor.","commonSituations":"A webhook route added to a project that previously only made outbound API calls; production .env missing WECHAT_TOKEN while local has it; refactors that construct the Server directly and drop the token argument.","solutions":["Set 'token' in the Application config to the value configured in the MP console server config","Or pass token (or an encryptor, which carries one) explicitly when constructing the Server","Clear the config cache and confirm the env var reaches the process (config:show / dump env)"],"exampleFix":"// before\n$config = ['app_id' => 'wx1234', 'secret' => '...'];\n$app = new \\EasyWeChat\\OfficialAccount\\Application($config);\n$app->getServer()->serve(); // InvalidConfigException: token required\n\n// after\n$config = ['app_id' => 'wx1234', 'secret' => '...',\n    'token' => env('WECHAT_TOKEN'), 'aes_key' => env('WECHAT_AES_KEY')];\n$app = new \\EasyWeChat\\OfficialAccount\\Application($config);\n$app->getServer()->serve();","handlingStrategy":"validation","validationCode":"if (blank($app->getConfig()->get('token'))) {\n    abort(503, 'callback endpoint active but WECHAT token not configured');\n}","typeGuard":null,"tryCatchPattern":"try {\n    return $app->getServer()->serve();\n} catch (\\EasyWeChat\\Kernel\\Exceptions\\InvalidConfigException $e) {\n    // serve() cannot validate signatures without a token: fail loudly, do not 200 'success'\n    return new \\Nyholm\\Psr7\\Response(503, [], 'server misconfigured');\n}","preventionTips":["Add 'token' to config the moment a callback route exists, even if encryption is off","Assert required WeChat keys in a boot-time config check per environment","Never return 200 from a webhook whose signature validation could not run"],"tags":["php","easywechat","wechat","official-account","config","webhook","signature"],"backgroundTag":"missing-required-config","analyzedSha":"f0cf0a8b8361417ed683b8246d0ecbaf0aafcaa8","analyzedAt":"2026-08-21T05:29:19.565Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}