{"record":{"id":"c3d52cbe57a9ff87","repo":"JeffreySu/WeiXinMPSDK","slug":"uri","errorCode":null,"errorMessage":"uri","messagePattern":"uri","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":1285,"sourceCode":"        #region 扩展方法\n        /// <summary>\n        /// 生成pay_sig\n        /// </summary>\n        /// <typeparam name=\"T\"></typeparam>\n        /// <param name=\"appKey\"></param>\n        /// <param name=\"uri\">例：/xpay/query_user_balance</param>\n        /// <param name=\"data\"></param>\n        /// <returns></returns>\n        /// <exception cref=\"System.ArgumentNullException\"></exception>\n        public static string GeneratePaySign<T>(string appKey, string uri, T data)\n        {\n            if (string.IsNullOrWhiteSpace(appKey))\n            {\n                throw new ArgumentNullException(\"appKey\");\n            }\n            if (string.IsNullOrWhiteSpace(uri))\n            {\n                throw new ArgumentNullException(\"uri\");\n            }\n            if (data == null)\n            {\n                throw new ArgumentNullException(\"data\");\n            }\n\n            var signData = JsonConvert.SerializeObject(data);\n            var rawData = $\"{uri}&{signData}\";\n\n            var keyBytes = Encoding.UTF8.GetBytes(appKey);\n            var dataBytes = Encoding.UTF8.GetBytes(rawData);\n            using (var hmac = new HMACSHA256(keyBytes))\n            {\n                var hashBytes = hmac.ComputeHash(dataBytes);\n                return BitConverter.ToString(hashBytes).Replace(\"-\", \"\").ToLower();\n            }\n        }\n","sourceCodeStart":1267,"sourceCodeEnd":1303,"githubUrl":"https://github.com/JeffreySu/WeiXinMPSDK/blob/be573f6f94bdbf718dd5f6cdecb137fbc7ff651e/src/Senparc.Weixin.WxOpen/src/Senparc.Weixin.WxOpen/Senparc.Weixin.WxOpen/AdvancedAPIs/XPay/XPayApi.cs#L1267-L1303","documentation":"XPayApi.GeneratePaySign throws ArgumentNullException when the uri parameter is null, empty, or whitespace. The uri (request URI path) is required as part of the raw signature string ($\"{uri}&{signData}\").","triggerScenarios":"Calling GeneratePaySign with uri = null or \"\", typically because the endpoint path constant was not passed or a config value is blank.","commonSituations":"Forgot to pass the API path (e.g. \"/xpay/query_user_balance\") when wrapping the call; refactoring removed the uri argument; config-driven uri not set.","solutions":["Pass the correct XPay endpoint URI string as the second argument","Define endpoint paths as constants to avoid null/empty values","Add a guard or default in your wrapper service"],"exampleFix":"// before\nvar sign = XPayApi.GeneratePaySign(appKey, null, data);\n// after\nvar sign = XPayApi.GeneratePaySign(appKey, \"/xpay/currency/pay\", data);","handlingStrategy":"validation","validationCode":"if (string.IsNullOrWhiteSpace(uri)) throw new InvalidOperationException(\"XPay endpoint URI is required\");","typeGuard":null,"tryCatchPattern":"try { return XPayApi.GeneratePaySign(appKey, uri, data); }\ncatch (ArgumentNullException ex) { logger.LogError(ex, \"XPay uri missing\"); throw; }","preventionTips":["Define XPay endpoint paths as constants","Avoid nullable config-bound URI values; default them to known endpoints","Add unit tests covering each signing call's arguments"],"tags":["wxopen","xpay","argument-null","signing"],"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"}