JeffreySu/WeiXinMPSDK · error · TenpayApiRequestException

tenPayV3Info 参数不能为空!

Error message

tenPayV3Info 参数不能为空!

What it means

This obsolete overload of GetJsApiUiPackage (deprecated since v2.4.0 in favor of the overload taking JsApiAppType) requires a populated TenPayV3Info configuration object containing appid, mch_id, key etc. to compute the JsApi pay-sign package. It throws when the tenPayV3Info argument is null, since no signature can be produced without the merchant's V3 credentials. The fix is for callers to pass a valid TenPayV3Info instance (e.g. TenPayV3InfoCollection.Data).

Solutions

  1. Ensure TenPayV3Info is registered/obtained before the call: TenPayV3InfoCollection.Register(...) and fetch from TenPayV3InfoCollection.Data[registerKey]
  2. Add a null check or assertion at the call site
  3. Pass the TenPayV3Info instance from DI or a config-backed factory instead of a local variable

Example fix

// before
TenPayV3Info info = null;
var package = TenPaySignHelper.GetJsApiUiPackage(prepayId, info);
// after
var info = TenPayV3InfoCollection.Data[TenPayHelper.GetRegisterKey(mchId, subMchId)];
var package = TenPaySignHelper.GetJsApiUiPackage(prepayId, info);
Defensive patterns

Strategy: validation

Validate before calling

if (tenPayV3Info == null)
    throw new InvalidOperationException("TenPayV3Info 未初始化:请先 TenPayV3InfoCollection.Register");

Type guard

bool HasTenpayInfo(string mchId, string subMchId) => TenPayV3InfoCollection.Data.ContainsKey(TenPayHelper.GetRegisterKey(mchId, subMchId));

Try / catch

try { var pkg = TenPaySignHelper.GetJsApiUiPackage(prepayId, info); }
catch (TenpayApiRequestException ex) { log.Error("tenPayV3Info 为空", ex); throw new AppConfigException("商户信息未注册", ex); }

Prevention

When it happens

Trigger: Calling GetJsApiUiPackage(prepayId, null) — usually because TenPayV3InfoCollection.Data[key] lookup returned nothing or a variable holding TenPayV3Info was never initialized.

Common situations: Merchant info not registered via TenPayV3InfoCollection.Register; using the wrong mchId register key so the lookup path produces null; refactoring code where the info object was removed.

Related errors


AI-assisted analysis of JeffreySu/WeiXinMPSDK@be573f6f94 (2026-09-12). Data as JSON: /api/errors/d8eb2744e9f0a1fc. Report an issue: GitHub.

Appendix: source

Thrown at src/Senparc.Weixin.TenPay/Senparc.Weixin.TenPayV3/Helpers/TenPaySignHelper.cs:315

        /// <param name="prepayId">预支付交易会话标识。</param>
        /// <param name="tenPayV3Info">微信支付 V3 配置信息。</param>
        /// <returns></returns>
        [Obsolete("v2.4.0 起该方法已过时,请使用 GetJsApiUiPackage(string prepayId, TenPayV3Info tenPayV3Info, JsApiAppType? appType) 方法。")]
        public static JsApiUiPackage GetJsApiUiPackage(string prepayId, TenPayV3Info tenPayV3Info)
            => GetJsApiUiPackage(prepayId, tenPayV3Info, JsApiAppType.WxOpen);

        /// <summary>
        /// 获取给 JsApi UI 使用的打包签名信息
        /// </summary>
        /// <param name="prepayId">预支付交易会话标识。</param>
        /// <param name="tenPayV3Info">微信支付 V3 配置信息。</param>
        /// <param name="appType">应用类型(小程序或原生 App)。</param>
        /// <returns></returns>
        public static JsApiUiPackage GetJsApiUiPackage(string prepayId, TenPayV3Info tenPayV3Info, JsApiAppType appType = JsApiAppType.WxOpen)
        {
            if (tenPayV3Info == null)
            {
                throw new Senparc.Weixin.TenPayV3.TenpayApiRequestException("tenPayV3Info 参数不能为空!");
            }

            var timeStamp = TenPayV3Util.GetTimestamp();
            var nonceStr = TenPayV3Util.GetNoncestr();
            var prepayIdPackage = GetPrepayIdPackage(prepayId, appType);
            var sign = TenPaySignHelper.CreatePaySign(timeStamp, nonceStr, prepayIdPackage, tenPayV3Info);

            JsApiUiPackage jsApiUiPackage = new(tenPayV3Info.AppId, timeStamp, nonceStr, prepayIdPackage, sign);
            return jsApiUiPackage;
        }

        /// <summary>
        /// 根据微信小程序或原生 APP 定义不同格式的 prepayId 签名字符串
        /// </summary>
        /// <param name="prepayId"></param>
        /// <param name="appType"></param>
        /// <returns></returns>
        private static string GetPrepayIdPackage(string prepayId, JsApiAppType appType)

View on GitHub (pinned to be573f6f94)