JeffreySu/WeiXinMPSDK · error · TenpayApiRequestException
当 为 时, 必填!,且 为null!
Error message
当 {nameof(data.partner.type)} 为 {data.partner.type} 时,{nameof(data.partner.appid)} 必填!,且{nameof(data.partner.merchant_id)}为null! What it means
BuildPartnershipsAsync (MarketingApis.Partnerships.cs:63) validates partner identification before building a marketing partnership. When partner.type is "APPID", WeChat requires the partner to be identified by appid and NOT by merchant_id; the library throws TenpayApiRequestException if appid is null or merchant_id is set in that mode.
Solutions
- Set data.partner.type = "APPID", assign data.partner.appid, and set data.partner.merchant_id = null
- If the partner should be identified by merchant number, use type "MERCHANT" with merchant_id set and appid null instead
- Validate the partner object (type vs field pairing) in your request-building code before calling
Example fix
// before data.partner.type = "APPID"; data.partner.merchant_id = "2480000000"; // invalid pairing // after data.partner.type = "APPID"; data.partner.appid = "wx1234567890"; data.partner.merchant_id = null;
Defensive patterns
Strategy: validation
Validate before calling
if (data.partner.type == "APPID" && (data.partner.appid is null || data.partner.merchant_id is not null))
throw new InvalidOperationException("APPID partner requires appid set and merchant_id null"); Type guard
bool PartnerIdValid(Partner p) =>
(p.type == "APPID" && p.appid != null && p.merchant_id == null) ||
(p.type == "MERCHANT" && p.merchant_id != null && p.appid == null); Try / catch
try { await api.BuildPartnershipsAsync(data); }
catch (TenpayApiRequestException ex) when (ex.Message.Contains("partner.appid"))
{ logger.LogError(ex, "Invalid APPID-type partner identification"); throw; } Prevention
- Keep partner type and identifier pairing in a single factory
- Null out the unused identifier when switching partner type
- Model type with an enum discriminated union instead of free strings
When it happens
Trigger: Calling BuildPartnershipsAsync with data.partner.type == "APPID" and either data.partner.appid left null or data.partner.merchant_id populated (both fields must follow the APPID rule: appid present, merchant_id null).
Common situations: Reusing a request object built for a MERCHANT-type partner and switching type to APPID without clearing merchant_id; forgetting to set appid when the partnership is defined by an appid; deserializing partner config from JSON that always contains merchant_id.
Related errors
AI-assisted analysis of JeffreySu/WeiXinMPSDK@be573f6f94 (2026-09-12).
Data as JSON: /api/errors/e2d7a6c5e415fdb7.
Report an issue: GitHub.
Appendix: source
Thrown at src/Senparc.Weixin.TenPay/Senparc.Weixin.TenPayV3/Apis/Marketing/MarketingApis.Partnerships.cs:63
/// https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_1.shtml 下的【营销工具】所有接口 > 【代金券接口】
/// </summary>
public partial class MarketingApis
{
#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>View on GitHub (pinned to be573f6f94)