JeffreySu/WeiXinMPSDK · error · TenpayApiRequestException
当 为 时, 必填!,且 为null!
Error message
当 {nameof(data.partner.type)} 为 {data.partner.type} 时,{nameof(data.partner.merchant_id)} 必填!,且{nameof(data.partner.merchant_id)}为null! What it means
BuildPartnershipsAsync (MarketingApis.Partnerships.cs:67) validates the MERCHANT-type partner: merchant_id is required and appid must not be set. If type is "MERCHANT" but appid is populated or merchant_id is null, the library throws TenpayApiRequestException before the API call. (Note: the message text erroneously mentions merchant_id twice — a typo in the library's message — but the condition is about merchant_id being required and appid being null.)
Solutions
- Set data.partner.merchant_id to the partner merchant number and clear data.partner.appid when type is "MERCHANT"
- If the partner should be appid-identified, keep type "APPID" with appid set and merchant_id null
- Add pairing validation in request construction to keep type and identifiers consistent
Example fix
// before data.partner.type = "MERCHANT"; data.partner.appid = "wx1234567890"; // must be null // after data.partner.type = "MERCHANT"; data.partner.appid = null; data.partner.merchant_id = "2480000000";
Defensive patterns
Strategy: validation
Validate before calling
if (data.partner.type == "MERCHANT" && (data.partner.merchant_id is null || data.partner.appid is not null))
throw new InvalidOperationException("MERCHANT partner requires merchant_id set and appid null"); Type guard
bool MerchantPartnerValid(Partner p) =>
p.type != "MERCHANT" || (p.merchant_id != null && p.appid == null); Try / catch
try { await api.BuildPartnershipsAsync(data); }
catch (TenpayApiRequestException ex) when (ex.Message.Contains("merchant_id"))
{ logger.LogError(ex, "Invalid MERCHANT-type partner identification"); throw; } Prevention
- Clear appid when partner type is MERCHANT
- Validate partner objects before any partnership build call
- Add unit tests for both partner type pairings
When it happens
Trigger: Calling BuildPartnershipsAsync with data.partner.type == "MERCHANT" while data.partner.merchant_id is null, or while data.partner.appid is still populated.
Common situations: Switching a previously APPID-typed partner to MERCHANT without clearing appid; forgetting to fill merchant_id for merchant-based partnerships; binding a partner object from config where appid is always present.
Related errors
AI-assisted analysis of JeffreySu/WeiXinMPSDK@be573f6f94 (2026-09-12).
Data as JSON: /api/errors/7cb91facaed6cbdf.
Report an issue: GitHub.
Appendix: source
Thrown at src/Senparc.Weixin.TenPay/Senparc.Weixin.TenPayV3/Apis/Marketing/MarketingApis.Partnerships.cs:67
#region 委托营销接口
/// <summary>
/// 建立合作关系接口
/// <para>该接口主要为商户提供营销资源的授权能力,可授权给其他商户或小程序,方便商户间的互利合作。</para>
/// <para>更多详细请参考 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter9_5_1.shtml </para>
/// </summary>
/// <param name="data">微信支付需要POST的Data数据</param>
/// <param name="timeOut">超时时间,单位为ms </param>
/// <returns></returns>
public async Task<BuildPartnershipsReturnJson> BuildPartnershipsAsync(BuildPartnershipsRequestData data, int timeOut = Config.TIME_OUT)
{
if (data.partner.type == "APPID" && (data.partner.appid is null || data.partner.merchant_id is not null))
{
throw new TenpayApiRequestException($"当 {nameof(data.partner.type)} 为 {data.partner.type} 时,{nameof(data.partner.appid)} 必填!,且{nameof(data.partner.merchant_id)}为null!");
}
if (data.partner.type == "MERCHANT" && (data.partner.appid is not null || data.partner.merchant_id is null))
{
throw new TenpayApiRequestException($"当 {nameof(data.partner.type)} 为 {data.partner.type} 时,{nameof(data.partner.merchant_id)} 必填!,且{nameof(data.partner.merchant_id)}为null!");
}
var url = BasePayApis.GetPayApiUrl(Senparc.Weixin.Config.TenPayV3Host + "/{0}v3/marketing/partnerships/build");
TenPayApiRequest tenPayApiRequest = new(_tenpayV3Setting);
return await tenPayApiRequest.RequestAsync<BuildPartnershipsReturnJson>(url, data, timeOut);
}
/// <summary>
/// 终止合作关系接口
/// <para>该接口主要为商户提供营销资源的终止授权能力,便于商户管理运营现存的合作关系。</para>
/// <para>更多详细请参考 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter9_5_2.shtml </para>
/// </summary>
/// <param name="data">微信支付需要POST的Data数据</param>
/// <param name="timeOut">超时时间,单位为ms </param>
/// <returns></returns>
public async Task<TerminatePartnershipsReturnJson> TerminatePartnershipsAsync(TerminatePartnershipsRequestData data, int timeOut = Config.TIME_OUT)
{
View on GitHub (pinned to be573f6f94)