JeffreySu/WeiXinMPSDK · error · TenpayApiRequestException
接收方类型为 MERCHANT_ID 时,name 必填。
Error message
接收方类型为 MERCHANT_ID 时,name 必填。
What it means
When adding profit-sharing receivers to a chain brand, a receiver whose type is MERCHANT_ID must carry a name (merchant name) per WeChat's API contract. CreateOrderAsync iterates the receivers collection and throws TenpayApiRequestException when any MERCHANT_ID receiver has a null/empty/whitespace name.
Solutions
- Set the name field on every MERCHANT_ID receiver before calling.
- Filter out or fix receivers with missing names in your service layer.
- Use PERSONAL type instead of MERCHANT_ID when the receiver is an individual and name is truly unavailable.
Example fix
// before
new ChainBrandProfitsharingReceiverRequestData { type = "MERCHANT_ID", account = mchId, name = null }
// after
new ChainBrandProfitsharingReceiverRequestData { type = "MERCHANT_ID", account = mchId, name = "商户全称" } Defensive patterns
Strategy: validation
Validate before calling
foreach (var r in receivers.Where(r => r?.type == "MERCHANT_ID"))
if (string.IsNullOrWhiteSpace(r.name)) throw new ArgumentException($"Receiver {r.account} needs a name."); Type guard
bool receiverValid(ChainBrandProfitsharingReceiverRequestData r) =>
r?.type != "MERCHANT_ID" || !string.IsNullOrWhiteSpace(r.name); Try / catch
try { await apis.CreateOrderAsync(brandId, orderData, receivers); }
catch (TenpayApiRequestException ex) when (ex.Message.Contains("MERCHANT_ID")) { logger.Warn(ex, "Receiver missing name"); throw new BusinessRuleException("Fill merchant name for all MERCHANT_ID receivers."); } Prevention
- Make the name field required in your receiver-creation UI for MERCHANT_ID type
- Backfill missing merchant names when syncing receivers
- Validate the whole receivers collection before any WeChat call
When it happens
Trigger: Calling CreateOrderAsync with receivers containing an entry where type == "MERCHANT_ID" and name is null or empty; constructing receiver objects dynamically from DB rows missing the merchant name column.
Common situations: Syncing receivers from an external system where the name field is optional there but mandatory here; template code copying PERSONAL-type receivers (name optional) for MERCHANT_ID.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
AI-assisted analysis of JeffreySu/WeiXinMPSDK@be573f6f94 (2026-09-12).
Data as JSON: /api/errors/72307fa67f54b7d0.
Report an issue: GitHub.
Appendix: source
Thrown at src/Senparc.Weixin.TenPay/Senparc.Weixin.TenPayV3/Apis/ChainBrandProfitsharing/ChainBrandProfitsharingApis.cs:75
/// <para>官方文档:https://pay.weixin.qq.com/doc/v3/partner/4012692975</para>
/// </summary>
/// <param name="data">品牌主、出资商户、订单和最多 50 个分账接收方。</param>
/// <param name="timeOut">代理请求超时时间(毫秒)。</param>
/// <returns>分账单和各接收方执行结果。</returns>
public async Task<ChainBrandProfitsharingOrderResultJson>
CreateOrderAsync(
ChainBrandProfitsharingCreateOrderRequestData data,
int timeOut = Config.TIME_OUT)
{
_ = data ?? throw new ArgumentNullException(nameof(data));
var receivers = data.receivers ??
Array.Empty<ChainBrandProfitsharingReceiverRequestData>();
foreach (var receiver in receivers)
{
if (receiver?.type == "MERCHANT_ID" &&
string.IsNullOrWhiteSpace(receiver.name))
{
throw new TenpayApiRequestException(
"接收方类型为 MERCHANT_ID 时,name 必填。");
}
}
var request = await CreateSensitiveRequestAsync(receivers
.Where(receiver => receiver != null &&
!string.IsNullOrWhiteSpace(receiver.name))
.Cast<object>()).ConfigureAwait(false);
const string path = "v3/brand/profitsharing/orders";
return await request.RequestAsync<
ChainBrandProfitsharingOrderResultJson>(GetUrl(path), data,
timeOut).ConfigureAwait(false);
}
/// <summary>
/// 查询连锁品牌分账结果。
/// <para>官方文档:https://pay.weixin.qq.com/doc/v3/partner/4012467002</para>
/// </summary>View on GitHub (pinned to be573f6f94)