JeffreySu/WeiXinMPSDK · error · TenpayApiRequestException
与 必填其中一个.不允许都填写或都不填写
Error message
{nameof(out_order_no)}与{query_id}必填其中一个.不允许都填写或都不填写 What it means
QueryServiceOrderAsync (PayScoreApis.cs:211) queries a WeChat Pay Score (支付分) service order, which must be identified by exactly one of out_order_no (merchant order number) or query_id. The library throws TenpayApiRequestException when both are null or both are provided, because WeChat requires exactly one query key.
Solutions
- Pass exactly one identifier: either out_order_no or query_id, leaving the other null
- Choose out_order_no when querying by your own order number, query_id when the id came from a WeChat callback/notification
- Wrap the call in a helper that asserts exactly one of the two values is present
Example fix
// before (both set — throws) await api.QueryServiceOrderAsync(outOrderNo, queryId, serviceId, appid); // after await api.QueryServiceOrderAsync(outOrderNo, null, serviceId, appid);
Defensive patterns
Strategy: validation
Validate before calling
if ((outOrderNo == null) == (queryId == null))
throw new InvalidOperationException("Exactly one of out_order_no / query_id must be provided"); Try / catch
try { await api.QueryServiceOrderAsync(outOrderNo, queryId, serviceId, appid); }
catch (TenpayApiRequestException ex) when (ex.Message.Contains("out_order_no"))
{ logger.LogError(ex, "Must pass exactly one of out_order_no/query_id"); throw; } Prevention
- Build a wrapper API taking a discriminated parameter (either order number or query id)
- Never pass both identifiers, even when both are known
- Add argument checks in your service layer before calling the SDK
When it happens
Trigger: Calling QueryServiceOrderAsync with both out_order_no and query_id null, or with both non-null; e.g. passing empty strings/logic that failed to choose one identifier.
Common situations: Copy-pasted call sites that always pass both arguments; business code that has both identifiers cached and forwards both; after a refactor where the query id became optional but the out_order_no path wasn't chosen exclusively.
Related errors
AI-assisted analysis of JeffreySu/WeiXinMPSDK@be573f6f94 (2026-09-12).
Data as JSON: /api/errors/1bf1dbddeabf6ebd.
Report an issue: GitHub.
Appendix: source
Thrown at src/Senparc.Weixin.TenPay/Senparc.Weixin.TenPayV3/Apis/PayScore/PayScoreApis.cs:211
return await tenPayApiRequest.RequestAsync<CreateServiceOrderReturnJson>(url, data, timeOut);
}
/// <summary>
/// 查询支付分订单接口
/// <para>用于查询单笔微信支付分订单详细信息。</para>
/// <para><see href="https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter6_1_15.shtml">更多详细请参考微信支付官方文档</see></para>
/// </summary>
/// <param name="out_order_no">商户系统内部服务订单号(不是交易单号),与创建订单时一致,商户单号与回跳查询id必填其中一个.不允许都填写或都不填写。</param>
/// <param name="query_id">微信侧回跳到商户前端时用于查单的单据查询id。详见章节“小程序跳转接口,回跳商户接口”,商户单号与回跳查询id必填其中一个.不允许都填写或都不填写。</param>
/// <param name="service_id">服务ID,该服务ID有本接口对应产品的权限</param>
/// <param name="appid"> 微信公众平台分配的与传入的商户号建立了支付绑定关系的appid,可在公众平台查看绑定关系,此参数需在本系统先进行配置。</param>
/// <param name="timeOut">超时时间,单位为ms</param>
/// <returns></returns>
public async Task<QueryServiceOrderReturnJson> QueryServiceOrderAsync(string out_order_no, string query_id, string service_id, string appid, int timeOut = Config.TIME_OUT)
{
if ((out_order_no is null && query_id is null) || (out_order_no is not null && query_id is not null))
{
throw new TenpayApiRequestException($"{nameof(out_order_no)}与{query_id}必填其中一个.不允许都填写或都不填写");
}
var url = ReurnPayApiUrl($"{Senparc.Weixin.Config.TenPayV3Host}/{{0}}v3/payscore/serviceorder?service_id={service_id}&appid={appid}");
url += out_order_no is not null ? $"&out_order_no={out_order_no}" : "";
url += query_id is not null ? $"&query_id={query_id}" : "";
TenPayApiRequest tenPayApiRequest = new(_tenpayV3Setting);
return await tenPayApiRequest.RequestAsync<QueryServiceOrderReturnJson>(url, null, timeOut, ApiRequestMethod.GET);
}
/// <summary>
/// 取消支付分订单接口
/// <para>微信支付分订单创建之后,由于某些原因导致订单不能正常支付时,可使用此接口取消订单。</para>
/// <para>订单为以下状态时可以取消订单:CREATED(已创单)、DOING(进行中)(包括商户完结支付分订单后,且支付分订单收款状态为待支付USER_PAYING)。</para>
/// <para>更多详细请参考 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter6_1_16.shtml </para>
/// </summary>View on GitHub (pinned to be573f6f94)