JeffreySu/WeiXinMPSDK · error · TenpayApiRequestException
sub_orders 参数必须在 2 到 10 之间!
Error message
sub_orders 参数必须在 2 到 10 之间!
What it means
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.
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.
Example fix
// before
if (orders.Count == 1) await apis.JsApiCombineAsync(data);
// after
if (orders.Count == 1)
await apis.JsApiAsync(data.ToSingleTransaction());
else
await apis.JsApiCombineAsync(data); Defensive patterns
Strategy: validation
Validate before calling
if (data?.sub_orders is { } orders && (orders.Count() < 2 || orders.Count() > 10))
throw new InvalidOperationException($"sub_orders must contain 2-10 orders, got {orders.Count()}."); Type guard
bool combineEligible = data?.sub_orders?.Count() is >= 2 and <= 10;
Try / catch
try { return await apis.JsApiCombineAsync(data); }
catch (TenpayApiRequestException ex) when (ex.Message.Contains("sub_orders")) { return await apis.JsApiAsync(singleOrderData); } Prevention
- 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
When it happens
Trigger: Calling JsApiCombineAsync with a CombineTransactionsRequestData whose sub_orders collection has 0 or 1 elements, or more than 10 elements.
Common situations: 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.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
AI-assisted analysis of JeffreySu/WeiXinMPSDK@be573f6f94 (2026-09-12).
Data as JSON: /api/errors/e5e5db902b473064.
Report an issue: GitHub.
Appendix: source
Thrown at src/Senparc.Weixin.TenPay/Senparc.Weixin.TenPayV3/Apis/BasePay/BasePayApis.cs:236
return await tenPayApiRequest.RequestAsync<JsApiReturnJson>(url, data, timeOut);
}
// TODO: 待测试
/// <summary>
/// JSAPI合单支付下单接口
/// <para>在微信支付服务后台生成JSAPI合单预支付交易单,返回预支付交易会话标识</para>
/// <para>https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter5_1_3.shtml</para>
/// </summary>
/// <param name="data">微信支付需要POST的Data数据</param>
/// <param name="timeOut">超时时间,单位为ms </param>
/// <returns></returns>
public async Task<JsApiReturnJson> JsApiCombineAsync(CombineTransactionsRequestData data, int timeOut = Config.TIME_OUT)
{
try
{
if (data.sub_orders.Count() is not >= 2 or not <= 10)
{
throw new TenpayApiRequestException("sub_orders 参数必须在 2 到 10 之间!");
}
var url = BasePayApis.GetPayApiUrl(Senparc.Weixin.Config.TenPayV3Host + "/{0}v3/combine-transactions/jsapi");
TenPayApiRequest tenPayApiRequest = new(_tenpayV3Setting);
return await tenPayApiRequest.RequestAsync<JsApiReturnJson>(url, data, timeOut);
}
catch (Exception ex)
{
SenparcTrace.BaseExceptionLog(ex);
return new JsApiReturnJson() { ResultCode = new TenPayApiResultCode() { ErrorMessage = ex.Message } };
}
}
/// <summary>
/// APP支付下单接口
/// <para>在微信支付服务后台生成APP支付预支付交易单,返回预支付交易会话标识</para>
/// </summary>
/// <param name="data">微信支付需要POST的Data数据</param>View on GitHub (pinned to be573f6f94)