{"record":{"id":"4628fb3cc417d250","repo":"iflytek/astron-agent","slug":"wechat-verify-ticket-missing","errorCode":"WECHAT_VERIFY_TICKET_MISSING","errorMessage":"WECHAT_VERIFY_TICKET_MISSING","messagePattern":"WECHAT_VERIFY_TICKET_MISSING","errorType":"error_code","errorClass":"BusinessException","httpStatus":null,"severity":"critical","filePath":"console/backend/hub/src/main/java/com/iflytek/astron/console/hub/service/wechat/impl/WechatThirdpartyServiceImpl.java","lineNumber":203,"sourceCode":"        } catch (Exception e) {\n            log.error(\"Failed to parse verify ticket from decrypted XML: {}\", decryptedXml, e);\n        }\n    }\n\n    @Override\n    public String getComponentAccessToken() {\n        RBucket<String> bucket = redissonClient.getBucket(COMPONENT_ACCESS_TOKEN_KEY);\n\n        if (bucket.isExists()) {\n            return bucket.get();\n        }\n\n        // Get verification ticket\n        RBucket<String> ticketBucket = redissonClient.getBucket(COMPONENT_VERIFY_TICKET_KEY);\n        String componentVerifyTicket = ticketBucket.get();\n\n        if (!StringUtils.hasText(componentVerifyTicket)) {\n            throw new BusinessException(ResponseEnum.WECHAT_VERIFY_TICKET_MISSING);\n        }\n\n        // Call WeChat API to get access token\n        String accessToken = requestComponentAccessTokenFromWechat(componentVerifyTicket);\n\n        // Cache access token\n        bucket.set(accessToken, ACCESS_TOKEN_EXPIRE);\n\n        log.info(\"Third-party platform access token retrieved successfully\");\n        return accessToken;\n    }\n\n    /**\n     * Set pre-binding status\n     */\n    private void setPreBindStatus(String appid, Integer botId, String uid) {\n        String preBindKey = PRE_BIND_KEY + appid;\n        RBucket<String> bucket = redissonClient.getBucket(preBindKey);","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/console/backend/hub/src/main/java/com/iflytek/astron/console/hub/service/wechat/impl/WechatThirdpartyServiceImpl.java#L185-L221","documentation":"WECHAT_VERIFY_TICKET_MISSING is thrown by getComponentAccessToken when the Redis bucket COMPONENT_VERIFY_TICKET_KEY holds no value. WeChat pushes the component_verify_ticket every 10 minutes; without a stored ticket the component_access_token cannot be requested.","triggerScenarios":"Calling getComponentAccessToken before WeChat ever delivered a verify ticket (fresh deployment, ticket push endpoint not configured/receiving), after Redis was flushed/persisted ticket expired, or the callback URL for ticket pushes is misconfigured in the WeChat open platform.","commonSituations":"New environment where the authorization ticket push URL isn't registered; Redis restart/eviction wiping the key; the message-handling endpoint that stores the ticket is down or rejecting WeChat's pushes; firewall blocking WeChat's callback servers.","solutions":["Verify the ticket-receiving endpoint is configured as the authorized-event URL in WeChat Open Platform and returns success to WeChat's pushes","Check Redis for COMPONENT_VERIFY_TICKET_KEY; if absent, wait for the next 10-minute push or trigger WeChat to resend by restarting ticket receipt","Confirm the component appid/encoding/AES key so ticket push messages decrypt and store correctly","Check logs of the ticket handler for decryption or storage failures"],"exampleFix":"// before\nString componentVerifyTicket = ticketBucket.get();\nif (!StringUtils.hasText(componentVerifyTicket)) {\n    throw new BusinessException(ResponseEnum.WECHAT_VERIFY_TICKET_MISSING);\n}\n// after\nString componentVerifyTicket = ticketBucket.get();\nif (!StringUtils.hasText(componentVerifyTicket)) {\n    log.error(\"component_verify_ticket missing in Redis; check ticket push endpoint and redis persistence\");\n    throw new BusinessException(ResponseEnum.WECHAT_VERIFY_TICKET_MISSING);\n}\n// root fix: ensure the ticket callback stores it:\nredissonClient.getBucket(COMPONENT_VERIFY_TICKET_KEY).set(ticket, 11, TimeUnit.MINUTES);","handlingStrategy":"fallback","validationCode":"// pre-check before requesting a component token\nString ticket = redissonClient.getBucket(COMPONENT_VERIFY_TICKET_KEY).get();\nif (!StringUtils.hasText(ticket)) {\n    // fail fast / alert ops: WeChat ticket push is not being received\n}","typeGuard":null,"tryCatchPattern":"try {\n    String token = wechatThirdpartyService.componentAccessToken();\n} catch (BusinessException e) {\n    if (ResponseEnum.WECHAT_VERIFY_TICKET_MISSING.getCode().equals(e.getCode())) {\n        alertOps(\"component_verify_ticket missing — check ticket push endpoint and Redis\");\n        // back off and retry after the next 10-minute WeChat push\n    }\n    throw e;\n}","preventionTips":["Register the authorized-event URL in WeChat Open Platform and confirm it returns success","Store the ticket in Redis with a TTL slightly longer than the 10-minute push interval","Monitor the ticket key with an alert when it approaches expiry","Verify AES/message decryption of ticket push messages after any appid/key change"],"tags":["java","wechat","redis","third-party-platform","configuration"],"backgroundTag":"missing-config-value","analyzedSha":"5e758547a83371a5a4b29dadf4ac03e8dd527635","analyzedAt":"2026-09-12T08:03:51.356Z","contentChangedAt":"2026-09-12T08:03:51.356Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}