{"record":{"id":"ee9483cd2c178cf9","repo":"JeffreySu/WeiXinMPSDK","slug":"sessionkey","errorCode":null,"errorMessage":"sessionKey","messagePattern":"sessionKey","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"src/Senparc.Weixin.WxOpen/src/Senparc.Weixin.WxOpen/Senparc.Weixin.WxOpen/AdvancedAPIs/XPay/XPayApi.cs","lineNumber":1316,"sourceCode":"            {\n                var hashBytes = hmac.ComputeHash(dataBytes);\n                return BitConverter.ToString(hashBytes).Replace(\"-\", \"\").ToLower();\n            }\n        }\n\n        /// <summary>\n        /// 生成signature\n        /// </summary>\n        /// <typeparam name=\"T\"></typeparam>\n        /// <param name=\"sessionKey\"></param>\n        /// <param name=\"data\"></param>\n        /// <returns></returns>\n        /// <exception cref=\"System.ArgumentNullException\"></exception>\n        public static string GenerateSignature<T>(string sessionKey, T data)\n        {\n            if (string.IsNullOrWhiteSpace(sessionKey))\n            {\n                throw new ArgumentNullException(\"sessionKey\");\n            }\n            if (data == null)\n            {\n                throw new ArgumentNullException(\"data\");\n            }\n\n            var signData = JsonConvert.SerializeObject(data);\n            var keyBytes = Encoding.UTF8.GetBytes(sessionKey);\n            var dataBytes = Encoding.UTF8.GetBytes(signData);\n\n            using (var hmac = new HMACSHA256(keyBytes))\n            {\n                var hashBytes = hmac.ComputeHash(dataBytes);\n                return BitConverter.ToString(hashBytes).Replace(\"-\", \"\").ToLower();\n            }\n        }\n        /// <summary>\n        /// 生成 iOS 会员订阅（wx.requestAppleSubscribeSign）所需的 pay_sig","sourceCodeStart":1298,"sourceCodeEnd":1334,"githubUrl":"https://github.com/JeffreySu/WeiXinMPSDK/blob/be573f6f94bdbf718dd5f6cdecb137fbc7ff651e/src/Senparc.Weixin.WxOpen/src/Senparc.Weixin.WxOpen/Senparc.Weixin.WxOpen/AdvancedAPIs/XPay/XPayApi.cs#L1298-L1334","documentation":"XPayApi.GenerateSignature throws ArgumentNullException when sessionKey is null, empty, or whitespace. The sessionKey (from wx.login code2session) is the HMAC key used to sign request data for virtual payment APIs.","triggerScenarios":"Calling GenerateSignature with a null/empty sessionKey — typically because code2session was never called, failed, or the cached session key expired and was evicted.","commonSituations":"Session key cache miss on a fresh server instance; user session expired and code2session was not re-run; storing the key in a session store that lost the entry.","solutions":["Re-run the code2session flow (jscode2session API) to obtain a fresh session_key before signing","Cache the sessionKey per openid and refresh on null/empty","Verify the login flow stores session_key and not just openid"],"exampleFix":"// before\nvar sign = XPayApi.GenerateSignature(sessionCache.Get(openid), data); // may be null\n// after\nvar sessionKey = sessionCache.Get(openid) ?? await GetNewSessionKeyAsync(code);\nvar sign = XPayApi.GenerateSignature(sessionKey, data);","handlingStrategy":"validation","validationCode":"if (string.IsNullOrWhiteSpace(sessionKey)) await RefreshSessionKeyAsync(openid, code);","typeGuard":"bool HasValidSessionKey(string sessionKey) => !string.IsNullOrWhiteSpace(sessionKey);","tryCatchPattern":"try { return XPayApi.GenerateSignature(sessionKey, data); }\ncatch (ArgumentNullException) { var fresh = await GetSessionKeyAsync(code); return XPayApi.GenerateSignature(fresh, data); }","preventionTips":["Always obtain session_key via code2session before XPay calls","Cache session keys per openid and refresh when missing/expired","Distinguish openid from session_key when persisting login results"],"tags":["wxopen","xpay","session-key","argument-null"],"backgroundTag":"null-argument","analyzedSha":"be573f6f94bdbf718dd5f6cdecb137fbc7ff651e","analyzedAt":"2026-09-12T10:01:50.733Z","contentChangedAt":"2026-09-12T10:01:50.733Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}