{"record":{"id":"7cb91facaed6cbdf","repo":"JeffreySu/WeiXinMPSDK","slug":"nameof-data-partner-type-data-partner-type-nameof-data-7cb91f","errorCode":null,"errorMessage":"当 {nameof(data.partner.type)} 为 {data.partner.type} 时，{nameof(data.partner.merchant_id)} 必填！，且{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":67,"sourceCode":"        #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>\n        /// <returns></returns>\n        public async Task<TerminatePartnershipsReturnJson> TerminatePartnershipsAsync(TerminatePartnershipsRequestData data, int timeOut = Config.TIME_OUT)\n        {\n","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/JeffreySu/WeiXinMPSDK/blob/be573f6f94bdbf718dd5f6cdecb137fbc7ff651e/src/Senparc.Weixin.TenPay/Senparc.Weixin.TenPayV3/Apis/Marketing/MarketingApis.Partnerships.cs#L49-L85","documentation":"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.)","triggerScenarios":"Calling BuildPartnershipsAsync with data.partner.type == \"MERCHANT\" while data.partner.merchant_id is null, or while data.partner.appid is still populated.","commonSituations":"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.","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"],"exampleFix":"// before\ndata.partner.type = \"MERCHANT\";\ndata.partner.appid = \"wx1234567890\";  // must be null\n\n// after\ndata.partner.type = \"MERCHANT\";\ndata.partner.appid = null;\ndata.partner.merchant_id = \"2480000000\";","handlingStrategy":"validation","validationCode":"if (data.partner.type == \"MERCHANT\" && (data.partner.merchant_id is null || data.partner.appid is not null))\n    throw new InvalidOperationException(\"MERCHANT partner requires merchant_id set and appid null\");","typeGuard":"bool MerchantPartnerValid(Partner p) =>\n    p.type != \"MERCHANT\" || (p.merchant_id != null && p.appid == null);","tryCatchPattern":"try { await api.BuildPartnershipsAsync(data); }\ncatch (TenpayApiRequestException ex) when (ex.Message.Contains(\"merchant_id\"))\n{ logger.LogError(ex, \"Invalid MERCHANT-type partner identification\"); throw; }","preventionTips":["Clear appid when partner type is MERCHANT","Validate partner objects before any partnership build call","Add unit tests for both partner type pairings"],"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"}