JeffreySu/WeiXinMPSDK · error · WeixinException
TenPayV3InfoCollection尚未注册Mch:
Error message
TenPayV3InfoCollection尚未注册Mch:{0} What it means
TenPayV3InfoCollection throws this WeixinException from its string indexer when the requested merchant (Mch) key is not present among the registered TenPayV3Info entries. Like the V2 collection, lookups must be preceded by Register; the indexer throws instead of returning null.
Solutions
- Register the merchant before use: TenPayV3InfoCollection.Register(new TenPayV3Info(appId, appSecret, mchId, key, certPath, certPassword, notifyUrl)) at application startup.
- Verify the indexer key exactly matches the registered MchId.
- Guard with a ContainsKey check (or wrap the lookup) before indexing in multi-tenant flows.
- Log the set of registered Mch keys at startup and compare with the failing key.
Example fix
// before
var v3Info = TenPayV3InfoCollection.Data[mchId]; // throws if unregistered
// after
if (TenPayV3InfoCollection.Data.ContainsKey(mchId))
{
var v3Info = TenPayV3InfoCollection.Data[mchId];
}
else
{
TenPayV3InfoCollection.Register(new TenPayV3Info(appId, appSecret, mchId, key, certPath, certPassword, notifyUrl));
} Defensive patterns
Strategy: try-catch
Validate before calling
bool mchRegistered = TenPayV3InfoCollection.Data.ContainsKey(mchId);
if (!mchRegistered) throw new InvalidOperationException($"Mch '{mchId}' is not registered. Call TenPayV3InfoCollection.Register at startup."); Type guard
bool TryGetTenPayV3Info(string mchId, out TenPayV3Info info)
{
if (TenPayV3InfoCollection.Data.ContainsKey(mchId)) { info = TenPayV3InfoCollection.Data[mchId]; return true; }
info = null; return false;
} Try / catch
try { var info = TenPayV3InfoCollection.Data[mchId]; }
catch (WeixinException ex) when (ex.Message.StartsWith("TenPayV3InfoCollection尚未注册Mch"))
{
log.Error(ex.Message);
throw new InvalidOperationException("Register the TenPay V3 merchant at application startup.", ex);
} Prevention
- Register all TenPay V3 merchants (appId, mchId, key, cert) during application startup.
- Trim and case-check MchId values when reading from configuration.
- Log registered Mch ids at startup to diagnose environment mismatches quickly.
- Use a ContainsKey guard before indexed access in multi-tenant payment flows.
- Add an integration test that resolves every configured merchant from the collection before deployment.
When it happens
Trigger: Accessing tenPayV3InfoCollection["someMchId"] where no TenPayV3Info with that MchId was registered via TenPayV3InfoCollection.Register(...) in the current application instance.
Common situations: TenPay V3 merchant credentials not registered at startup; MchId typo, trailing space, or case mismatch; configuration registered in a different environment (dev vs prod app pool); multi-tenant systems indexing by a merchant id that was never added.
Related errors
- WeixinPayInfoCollection尚未注册Partner:
- 未获取到用于安全探测的微信支付公钥或平台证书。
- 没有设置证书加密类型(EncryptionType)
- tenPayV3Info 参数不能为空!
- Section is not found.
AI-assisted analysis of JeffreySu/WeiXinMPSDK@be573f6f94 (2026-09-12).
Data as JSON: /api/errors/f74ec895feb01b45.
Report an issue: GitHub.
Appendix: source
Thrown at src/Senparc.Weixin.TenPay/Senparc.Weixin.TenPay/V3/TenPayV3InfoCollection.cs:105
Senparc.Weixin.Config.SenparcWeixinSetting.Items[name].TenPayV3_WxOpenTenpayNotify = tenPayV3Info.TenPayV3_WxOpenNotify;
Senparc.Weixin.Config.SenparcWeixinSetting.Items[name].TenPayV3_SubMchId = tenPayV3Info.Sub_MchId;
Senparc.Weixin.Config.SenparcWeixinSetting.Items[name].TenPayV3_SubAppId = tenPayV3Info.Sub_AppId;
Senparc.Weixin.Config.SenparcWeixinSetting.Items[name].TenPayV3_SubAppSecret = tenPayV3Info.Sub_AppSecret;
}
}
/// <summary>
/// 索引 TenPayV3Info
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public new TenPayV3Info this[string key]
{
get
{
if (!base.ContainsKey(key))
{
throw new WeixinException(string.Format("TenPayV3InfoCollection尚未注册Mch:{0}", key));
}
else
{
return base[key];
}
}
set
{
base[key] = value;
}
}
/// <summary>
/// TenPayV3InfoCollection 构造函数
/// </summary>
public TenPayV3InfoCollection() : base(StringComparer.OrdinalIgnoreCase)
{
View on GitHub (pinned to be573f6f94)