{"record":{"id":"dab30caf8ba866ba","repo":"binarywang/WxJava","slug":"error-dab30c","errorCode":null,"errorMessage":"签名错误","messagePattern":"签名错误","errorType":"exception","errorClass":"WxErrorException","httpStatus":null,"severity":"error","filePath":"weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaInternetServiceImpl.java","lineNumber":51,"sourceCode":"    for (byte item : array) {\n      sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));\n    }\n    return sb.toString().toUpperCase();\n  }\n\n  @Override\n  public WxMaInternetResponse getUserEncryptKey(String openid, String signature, String sigMethod) throws WxErrorException {\n    String url = WxMaApiUrlConstants.Internet.GET_USER_ENCRYPT_KEY + \"?openid=\" + openid + \"&signature=\" + signature + \"&sig_method=\" + sigMethod;\n    return getWxMaInternetResponse(url);\n  }\n\n  @Override\n  public WxMaInternetResponse getUserEncryptKey(String openid, String sessionKey) throws WxErrorException {\n    String signature = null;\n    try {\n      signature = sha256(\"\", sessionKey);\n    } catch (Exception e) {\n      throw new WxErrorException(\"签名错误\");\n    }\n    String url = WxMaApiUrlConstants.Internet.GET_USER_ENCRYPT_KEY + \"?sig_method=hmac_sha256&openid=\" + openid + \"&signature=\" + signature;\n    return getWxMaInternetResponse(url);\n  }\n\n  private WxMaInternetResponse getWxMaInternetResponse(String url) throws WxErrorException {\n    String responseContent = this.wxMaService.post(url, \"\");\n    WxMaInternetResponse response = WxMaGsonBuilder.create().fromJson(responseContent, WxMaInternetResponse.class);\n    if (response.getErrcode() != null && response.getErrcode() != 0) {\n      throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp));\n    }\n    return response;\n  }\n}\n","sourceCodeStart":33,"sourceCodeEnd":66,"githubUrl":"https://github.com/binarywang/WxJava/blob/1c43293a3c2c9d7e91304b6d037fb017f680d0c6/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaInternetServiceImpl.java#L33-L66","documentation":"Thrown by the 2-arg getUserEncryptKey(openid, sessionKey) when the local HMAC-SHA256 computation in sha256(\"\", sessionKey) raises any exception; the catch block swallows the real cause and rethrows a generic WxErrorException(\"签名错误\"). This is a CLIENT-SIDE signature computation failure, not a WeChat server rejection. The sha256 helper calls sessionKey.getBytes(StandardCharsets.UTF_8), so a null sessionKey is the dominant trigger; Mac.getInstance(\"HmacSHA256\") failure is effectively impossible on a standard JVM.","triggerScenarios":"Calling wxMaService.getInternetService().getUserEncryptKey(openid, sessionKey) with a null (or never-obtained) sessionKey. Occurs when jscode2session was never called, the session key expired before this call, or the wrong value (e.g. openid) was passed in the sessionKey slot.","commonSituations":"Backend skipped code2Session before requesting the encrypt key; sessionKey expired past WeChat's short TTL and was read as null from cache; deserializing a stored session that was missing; passing openid where sessionKey belongs.","solutions":["Ensure sessionKey is non-null by obtaining it fresh via wxMaService.getUserService().getSessionInfo(jsCode) (jscode2session) immediately before calling getUserEncryptKey.","Guard the input: if sessionKey is null/blank, re-run the mini-program login flow instead of calling getUserEncryptKey.","Cache sessionKey with a TTL under WeChat's expiry and refresh when it returns null."],"exampleFix":"// before\nWxMaInternetResponse resp = internetService.getUserEncryptKey(openid, sessionKey);\n\n// after\nif (sessionKey == null || sessionKey.trim().isEmpty()) {\n  throw new IllegalStateException(\"sessionKey 缺失，请重新登录\");\n}\nWxMaInternetResponse resp = internetService.getUserEncryptKey(openid, sessionKey);","handlingStrategy":"validation","validationCode":"if (sessionKey == null || sessionKey.trim().isEmpty()) {\n  throw new IllegalArgumentException(\"sessionKey 不能为空，请先调用 jscode2session\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  response = internetService.getUserEncryptKey(openid, sessionKey);\n} catch (WxErrorException e) {\n  if (\"签名错误\".equals(e.getMessage())) {\n    // sessionKey missing/invalid — re-run the mini-program login flow\n  }\n  throw e;\n}","preventionTips":["Always obtain sessionKey via code2Session immediately before calling getUserEncryptKey.","Cache sessionKey with a TTL under WeChat's expiry and refresh on null.","Never pass openid in the sessionKey position."],"tags":["signature","session-key","null-check","miniapp","hmac-sha256"],"backgroundTag":null,"analyzedSha":"1c43293a3c2c9d7e91304b6d037fb017f680d0c6","analyzedAt":"2026-08-14T02:29:11.060Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}