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

  1. Set data.partner.type = "APPID", assign data.partner.appid, and set data.partner.merchant_id = null
  2. If the partner should be identified by merchant number, use type "MERCHANT" with merchant_id set and appid null instead
  3. 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

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)