{"record":{"id":"50eb0a85375b0e76","repo":"JeffreySu/WeiXinMPSDK","slug":"argumentnullexception-request-is-null","errorCode":null,"errorMessage":"ArgumentNullException (request is null)","messagePattern":"ArgumentNullException \\(request is null\\)","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"src/Senparc.Weixin.Work/Senparc.Weixin.Work/AdvancedAPIs/PayTool/PayToolSignatureHelper.cs","lineNumber":40,"sourceCode":"namespace Senparc.Weixin.Work.AdvancedAPIs.PayTool\n{\n    /// <summary>\n    /// 企业微信收款工具 HMAC-SHA256 签名辅助方法。\n    /// </summary>\n    public static class PayToolSignatureHelper\n    {\n        /// <summary>\n        /// 为收款工具请求补齐随机串、Unix 时间戳和数字签名。\n        /// 已提供签名时不会重新签名，并要求调用方同时提供原签名对应的随机串和时间戳。\n        /// </summary>\n        /// <param name=\"request\">需要签名的收款工具请求。</param>\n        /// <param name=\"payToolApiSecret\">收银台 API 调用密钥；请求未预签名时必填。</param>\n        public static void PrepareRequest(PayToolSignedRequestBase request,\n            string payToolApiSecret)\n        {\n            if (request == null)\n            {\n                throw new ArgumentNullException(nameof(request));\n            }\n\n            if (!string.IsNullOrEmpty(request.sig))\n            {\n                if (string.IsNullOrEmpty(request.nonce_str) || request.ts <= 0)\n                {\n                    throw new ArgumentException(\"预签名请求必须同时提供 nonce_str 和 ts。\",\n                        nameof(request));\n                }\n\n                return;\n            }\n\n            if (string.IsNullOrEmpty(payToolApiSecret))\n            {\n                throw new ArgumentException(\"请求未提供 sig 时必须提供收银台 API 调用密钥。\",\n                    nameof(payToolApiSecret));\n            }","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/JeffreySu/WeiXinMPSDK/blob/be573f6f94bdbf718dd5f6cdecb137fbc7ff651e/src/Senparc.Weixin.Work/Senparc.Weixin.Work/AdvancedAPIs/PayTool/PayToolSignatureHelper.cs#L22-L58","documentation":"PayToolSignatureHelper.PrepareRequest signs (or validates pre-signature fields of) a WeChat Work PayTool (收银台) API request. It throws ArgumentNullException when the request object itself is null, because no signature parameters can be computed without it.","triggerScenarios":"Calling PrepareRequest(null, payToolApiSecret) — e.g. a factory/builder returned null or a deserialized request was null before signature preparation.","commonSituations":"API response/deserialization produced a null request model; a conditional code path skipped request construction; unit tests passing null; refactoring where the request creation moved after the PrepareRequest call.","solutions":["Construct the PayToolSignedRequestBase instance (e.g. PayToolOrderRequest) before calling PrepareRequest","Check the code path that produced the request and ensure it always returns a populated object","Add a null check at the call site before invoking PrepareRequest"],"exampleFix":"// before\nPayToolSignedRequestBase req = CreateRequest(); // may be null\nPayToolSignatureHelper.PrepareRequest(req, apiSecret);\n// after\nPayToolSignedRequestBase req = CreateRequest() ?? throw new InvalidOperationException(\"request not built\");\nPayToolSignatureHelper.PrepareRequest(req, apiSecret);","handlingStrategy":"validation","validationCode":"if (request is null) throw new InvalidOperationException(\"PayTool request must be constructed before PrepareRequest\");","typeGuard":"bool IsReady(PayToolSignedRequestBase r) => r is not null;","tryCatchPattern":"try { PayToolSignatureHelper.PrepareRequest(req, apiSecret); }\ncatch (ArgumentNullException ex) { logger.LogError(ex, \"Request was null\"); return null; }","preventionTips":["Build the request model immediately before signing","Enable nullable reference types to catch null request flows","Avoid factory methods that can return null; throw instead"],"tags":["null-reference","argument-validation","signature","payment","wechat-work"],"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"}