{"record":{"id":"e5e5db902b473064","repo":"JeffreySu/WeiXinMPSDK","slug":"sub-orders-2-10","errorCode":null,"errorMessage":"sub_orders 参数必须在 2 到 10 之间！","messagePattern":"sub_orders 参数必须在 2 到 10 之间！","errorType":"validation","errorClass":"TenpayApiRequestException","httpStatus":null,"severity":"error","filePath":"src/Senparc.Weixin.TenPay/Senparc.Weixin.TenPayV3/Apis/BasePay/BasePayApis.cs","lineNumber":236,"sourceCode":"            return await tenPayApiRequest.RequestAsync<JsApiReturnJson>(url, data, timeOut);\n        }\n\n        // TODO: 待测试\n        /// <summary>\n        /// JSAPI合单支付下单接口\n        /// <para>在微信支付服务后台生成JSAPI合单预支付交易单，返回预支付交易会话标识</para>\n        /// <para>https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter5_1_3.shtml</para>\n        /// </summary>\n        /// <param name=\"data\">微信支付需要POST的Data数据</param>\n        /// <param name=\"timeOut\">超时时间，单位为ms </param>\n        /// <returns></returns>\n        public async Task<JsApiReturnJson> JsApiCombineAsync(CombineTransactionsRequestData data, int timeOut = Config.TIME_OUT)\n        {\n            try\n            {\n                if (data.sub_orders.Count() is not >= 2 or not <= 10)\n                {\n                    throw new TenpayApiRequestException(\"sub_orders 参数必须在 2 到 10 之间！\");\n                }\n\n                var url = BasePayApis.GetPayApiUrl(Senparc.Weixin.Config.TenPayV3Host + \"/{0}v3/combine-transactions/jsapi\");\n                TenPayApiRequest tenPayApiRequest = new(_tenpayV3Setting);\n                return await tenPayApiRequest.RequestAsync<JsApiReturnJson>(url, data, timeOut);\n            }\n            catch (Exception ex)\n            {\n                SenparcTrace.BaseExceptionLog(ex);\n                return new JsApiReturnJson() { ResultCode = new TenPayApiResultCode() { ErrorMessage = ex.Message } };\n            }\n        }\n\n        /// <summary>\n        /// APP支付下单接口\n        /// <para>在微信支付服务后台生成APP支付预支付交易单，返回预支付交易会话标识</para>\n        /// </summary>\n        /// <param name=\"data\">微信支付需要POST的Data数据</param>","sourceCodeStart":218,"sourceCodeEnd":254,"githubUrl":"https://github.com/JeffreySu/WeiXinMPSDK/blob/be573f6f94bdbf718dd5f6cdecb137fbc7ff651e/src/Senparc.Weixin.TenPay/Senparc.Weixin.TenPayV3/Apis/BasePay/BasePayApis.cs#L218-L254","documentation":"WeChat Pay's combine-transactions (合单支付) JSAPI endpoint requires between 2 and 10 sub-orders. JsApiCombineAsync validates data.sub_orders count and throws TenpayApiRequestException if the count falls outside that range, since WeChat would reject the request anyway.","triggerScenarios":"Calling JsApiCombineAsync with a CombineTransactionsRequestData whose sub_orders collection has 0 or 1 elements, or more than 10 elements.","commonSituations":"Building a single-order payment but using the combine API by mistake; passing an empty list because sub-orders failed to load; dynamically building orders where one item filtered out leaving only one.","solutions":["Ensure at least 2 and at most 10 sub-orders are populated before calling.","For single-order payments use the regular JsApiAsync (v3/pay/transactions/jsapi) instead of the combine API.","Add a count check in your own service layer to route single orders to the non-combine API."],"exampleFix":"// before\nif (orders.Count == 1) await apis.JsApiCombineAsync(data);\n// after\nif (orders.Count == 1)\n    await apis.JsApiAsync(data.ToSingleTransaction());\nelse\n    await apis.JsApiCombineAsync(data);","handlingStrategy":"validation","validationCode":"if (data?.sub_orders is { } orders && (orders.Count() < 2 || orders.Count() > 10))\n    throw new InvalidOperationException($\"sub_orders must contain 2-10 orders, got {orders.Count()}.\");","typeGuard":"bool combineEligible = data?.sub_orders?.Count() is >= 2 and <= 10;","tryCatchPattern":"try { return await apis.JsApiCombineAsync(data); }\ncatch (TenpayApiRequestException ex) when (ex.Message.Contains(\"sub_orders\")) { return await apis.JsApiAsync(singleOrderData); }","preventionTips":["Route single-order payments to the regular JsApi API, not combine","Check sub-orders count before calling combine APIs","Keep the 2-10 constraint documented next to order-grouping logic"],"tags":["argument-validation","range-check","wechat-pay"],"backgroundTag":"value-out-of-range","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"}