{"record":{"id":"e2d7a6c5e415fdb7","repo":"JeffreySu/WeiXinMPSDK","slug":"nameof-data-partner-type-data-partner-type-nameof-data","errorCode":null,"errorMessage":"当 {nameof(data.partner.type)} 为 {data.partner.type} 时，{nameof(data.partner.appid)} 必填！，且{nameof(data.partner.merchant_id)}为null！","messagePattern":"当 (.+?) 为 (.+?) 时，(.+?) 必填！，且(.+?)为null！","errorType":"validation","errorClass":"TenpayApiRequestException","httpStatus":null,"severity":"error","filePath":"src/Senparc.Weixin.TenPay/Senparc.Weixin.TenPayV3/Apis/Marketing/MarketingApis.Partnerships.cs","lineNumber":63,"sourceCode":"    /// https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_1.shtml 下的【营销工具】所有接口 &gt; 【代金券接口】\n    /// </summary>\n    public partial class MarketingApis\n    {\n        #region 委托营销接口\n\n        /// <summary>\n        /// 建立合作关系接口\n        /// <para>该接口主要为商户提供营销资源的授权能力，可授权给其他商户或小程序，方便商户间的互利合作。</para>\n        /// <para>更多详细请参考 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter9_5_1.shtml </para>\n        /// </summary>\n        /// <param name=\"data\">微信支付需要POST的Data数据</param>\n        /// <param name=\"timeOut\">超时时间，单位为ms </param>\n        /// <returns></returns>\n        public async Task<BuildPartnershipsReturnJson> BuildPartnershipsAsync(BuildPartnershipsRequestData data, int timeOut = Config.TIME_OUT)\n        {\n            if (data.partner.type == \"APPID\" && (data.partner.appid is null || data.partner.merchant_id is not null))\n            {\n                throw new TenpayApiRequestException($\"当 {nameof(data.partner.type)} 为 {data.partner.type} 时，{nameof(data.partner.appid)} 必填！，且{nameof(data.partner.merchant_id)}为null！\");\n            }\n            if (data.partner.type == \"MERCHANT\" && (data.partner.appid is not null || data.partner.merchant_id is null))\n            {\n                throw new TenpayApiRequestException($\"当 {nameof(data.partner.type)} 为 {data.partner.type} 时，{nameof(data.partner.merchant_id)} 必填！，且{nameof(data.partner.merchant_id)}为null！\");\n            }\n\n            var url = BasePayApis.GetPayApiUrl(Senparc.Weixin.Config.TenPayV3Host + \"/{0}v3/marketing/partnerships/build\");\n            TenPayApiRequest tenPayApiRequest = new(_tenpayV3Setting);\n            return await tenPayApiRequest.RequestAsync<BuildPartnershipsReturnJson>(url, data, timeOut);\n        }\n\n        /// <summary>\n        /// 终止合作关系接口\n        /// <para>该接口主要为商户提供营销资源的终止授权能力，便于商户管理运营现存的合作关系。</para>\n        /// <para>更多详细请参考 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter9_5_2.shtml </para>\n        /// </summary>\n        /// <param name=\"data\">微信支付需要POST的Data数据</param>\n        /// <param name=\"timeOut\">超时时间，单位为ms </param>","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/JeffreySu/WeiXinMPSDK/blob/be573f6f94bdbf718dd5f6cdecb137fbc7ff651e/src/Senparc.Weixin.TenPay/Senparc.Weixin.TenPayV3/Apis/Marketing/MarketingApis.Partnerships.cs#L45-L81","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\ndata.partner.type = \"APPID\";\ndata.partner.merchant_id = \"2480000000\"; // invalid pairing\n\n// after\ndata.partner.type = \"APPID\";\ndata.partner.appid = \"wx1234567890\";\ndata.partner.merchant_id = null;","handlingStrategy":"validation","validationCode":"if (data.partner.type == \"APPID\" && (data.partner.appid is null || data.partner.merchant_id is not null))\n    throw new InvalidOperationException(\"APPID partner requires appid set and merchant_id null\");","typeGuard":"bool PartnerIdValid(Partner p) =>\n    (p.type == \"APPID\" && p.appid != null && p.merchant_id == null) ||\n    (p.type == \"MERCHANT\" && p.merchant_id != null && p.appid == null);","tryCatchPattern":"try { await api.BuildPartnershipsAsync(data); }\ncatch (TenpayApiRequestException ex) when (ex.Message.Contains(\"partner.appid\"))\n{ logger.LogError(ex, \"Invalid APPID-type partner identification\"); throw; }","preventionTips":["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"],"tags":["tenpay","marketing","partnerships","validation"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"be573f6f94bdbf718dd5f6cdecb137fbc7ff651e","analyzedAt":"2026-09-12T10:01:50.733Z","contentChangedAt":"2026-09-12T10:01:50.733Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}