PAYATHON 2026

WeChat JSAPI 支付报错 appidget_brand_wcpay_request

支付小周

结论

appidget_brand_wcpay_request 不是完整、标准的微信支付错误码。它很可能是下面这段代码把多个返回字段直接拼接后得到的字符串:

alert(res.err_code + res.err_desc + res.err_msg);

字段之间没有分隔符,真实的错误信息因此混在了一起。从字符串里的 appid 和 get_brand_wcpay_request 来看,问题通常与支付参数格式、appId 不匹配、支付授权目录配置有关,也可能是后端返回的内容并非 JavaScript 对象。

先输出完整的回调结果和 /RenewPay/GetData 的原始响应,再根据具体字段排查。

先打印真实错误

不要再直接拼接 err_code、err_desc 和 err_msg,改为:

WeixinJSBridge.invoke('getBrandWCPayRequest', payData, function (res) {
    console.log("WeChat Pay result:", res);
    alert(JSON.stringify(res));
});

重点查看 res.err_msg,常见结果有:

get_brand_wcpay_request:ok
get_brand_wcpay_request:cancel
get_brand_wcpay_request:fail

它们分别表示:

  • ok:用户完成了支付调用,但最终支付状态仍应以后端支付通知或主动查单结果为准。
  • cancel:用户主动取消了支付。
  • fail:参数、签名、商户配置或授权关系存在问题。

部分环境不会返回 err_code 和 err_desc,因此不能假定这两个字段一定有值。

检查后端返回的数据类型

WeixinJSBridge.invoke() 的第二个参数必须是对象。如果 ASP.NET MVC 返回的是 JSON 字符串,前端需要先解析。

可以明确指定 JSON 响应:

function jsApiCall() {
    $.ajax({
        url: "/RenewPay/GetData",
        type: "GET",
        dataType: "json",
        success: function (data) {
            var payData = data;

            if (typeof payData === "string") {
                payData = JSON.parse(payData);
            }

            console.log("Payment parameters:", payData);

            WeixinJSBridge.invoke(
                "getBrandWCPayRequest",
                payData,
                function (res) {
                    console.log("WeChat Pay result:", res);
                    alert(JSON.stringify(res));
                }
            );
        },
        error: function (xhr) {
            console.error("GetData failed:", xhr.status, xhr.responseText);
            alert("获取支付参数失败");
        }
    });
}

后端不要对对象进行二次 JSON 序列化。例如,在 MVC 中可以直接返回:

return Json(new
{
    appId = appId,
    timeStamp = timeStamp,
    nonceStr = nonceStr,
    package = packageValue,
    signType = "MD5",
    paySign = paySign
}, JsonRequestBehavior.AllowGet);

不要写成:

return Json(JsonConvert.SerializeObject(payData));

后一种写法容易让前端拿到 JSON 字符串,而不是支付参数对象。

核对参数名称和格式

调用 getBrandWCPayRequest 时,参数名称区分大小写。典型结构如下:

{
    appId: "wx1234567890abcdef",
    timeStamp: "1700000000",
    nonceStr: "random-string",
    package: "prepay_id=wx201410272009395522657a690389285100",
    signType: "MD5",
    paySign: "SIGNATURE"
}

需要逐项检查:

  • 字段名必须是 appId,不能写成 appid 或 AppId。
  • 字段名必须是 timeStamp,不能写成 timestamp 或 TimeStamp。
  • 字段名必须是 nonceStr,不能写成 noncestr 或 NonceStr。
  • package 必须采用 prepay_id=... 的形式。
  • timeStamp 通常应以字符串形式传递。
  • signType 必须与生成 paySign 时使用的签名方式一致。
  • paySign 必须使用商户支付密钥,按对应接口规则生成,不能使用公众号的 AppSecret。
  • 不能把统一下单请求的 sign 直接用作前端调起支付所需的 paySign。前端参数需要按规定重新签名。

还要特别留意 ASP.NET 的属性命名。直接序列化 C# 模型时,可能输出:

{
  "AppId": "...",
  "TimeStamp": "...",
  "NonceStr": "..."
}

这些字段名不符合微信支付要求。应使用匿名对象、序列化属性标注或序列化命名策略,保证最终 JSON 中的字段大小写正确。

核对 appId、openid 和商户号的关系

支付参数中的 appId 必须是当前发起 JSAPI 支付的公众号 AppID,而且要在以下环节中保持一致:

  1. 用户通过该公众号对应的微信网页完成 OAuth 授权。
  2. 统一下单时使用该公众号的 appId。
  3. 统一下单中的 openid 属于该 appId。
  4. 商户号已与该公众号 AppID 建立正确的支付授权或绑定关系。
  5. 前端调起支付时仍然使用同一个 appId。

常见问题包括:

  • 使用公众号 A 获取的 openid,却用公众号 B 的 appId 下单。
  • 后端配置的是测试环境或其他公众号的 AppID。
  • 用小程序 AppID 或开放平台应用 AppID 代替公众号 AppID。
  • 商户号没有与当前公众号建立对应关系。

如果错误信息中明确出现 appid,应优先检查这些配置是否一致。

核对统一下单结果

前端调起支付之前,后端必须先成功创建 JSAPI 预支付订单。确认统一下单参数中包含:

trade_type = JSAPI

同时,统一下单响应中应返回有效的:

prepay_id

不能只看 HTTP 请求是否成功,还要检查微信返回的业务字段。不同版本的微信支付 API 使用的具体字段可能不同,但处理原则相同:只有下单成功并取得有效的预支付标识,才能生成前端支付参数。

同时确认以下事项:

  • 订单号没有被其他订单重复使用。
  • 金额和币种符合接口要求。
  • 回调地址可以被微信支付服务器访问。
  • prepay_id 没有过期。
  • 服务器时间正确,生成的时间戳没有明显偏差。
  • 参与签名的字段、字段大小写、排序方式和密钥均符合当前 API 版本的规则。

不要混用不同版本的下单接口、签名算法和前端调起参数。

核对 JSAPI 支付授权目录

公众号后台配置的 JS 接口安全域名,与微信支付商户平台中的 JSAPI 支付授权目录不是同一项配置,两者解决的问题也不同。

假设支付页面地址是:

https://www.example.com/RenewPay/Index

需要在微信支付商户平台中配置与页面路径匹配的 JSAPI 支付授权目录,例如:

https://www.example.com/RenewPay/

检查时注意:

  • 应使用实际发起支付页面的 URL,而不是 /RenewPay/GetData 接口地址。
  • 协议、域名、端口和路径必须与实际页面一致。
  • 如果支付页面发生重定向,以微信中最终打开的页面地址为准。
  • 测试域名、正式域名和不同子域名需要分别核对。
  • 页面必须通过微信内置浏览器打开。

只配置公众号的 JSAPI 或 JS 接口安全域名,不能代替商户平台中的支付授权目录配置。

推荐的前端实现

function requestPayment() {
    $.ajax({
        url: "/RenewPay/GetData",
        type: "GET",
        dataType: "json",
        cache: false,
        success: function (data) {
            var payData = typeof data === "string"
                ? JSON.parse(data)
                : data;

            console.log("Payment parameters:", payData);

            WeixinJSBridge.invoke(
                "getBrandWCPayRequest",
                payData,
                function (res) {
                    console.log("Payment callback:", res);

                    switch (res.err_msg) {
                        case "get_brand_wcpay_request:ok":
                            // 这里不能作为最终到账依据,应向后端查询订单状态
                            window.location.href = "/RenewPay/Result";
                            break;

                        case "get_brand_wcpay_request:cancel":
                            alert("支付已取消");
                            break;

                        default:
                            alert("支付调用失败:" + JSON.stringify(res));
                            break;
                    }
                }
            );
        },
        error: function (xhr) {
            console.error(xhr.status, xhr.responseText);
            alert("无法获取支付参数");
        }
    });
}

function callpay() {
    if (typeof WeixinJSBridge === "undefined") {
        if (document.addEventListener) {
            document.addEventListener(
                "WeixinJSBridgeReady",
                requestPayment,
                false
            );
        } else if (document.attachEvent) {
            document.attachEvent(
                "WeixinJSBridgeReady",
                requestPayment
            );
            document.attachEvent(
                "onWeixinJSBridgeReady",
                requestPayment
            );
        }
    } else {
        requestPayment();
    }
}

按钮可以直接绑定调用函数:

<button type="button" onclick="callpay()">Pay Now</button>

建议的排查顺序

按以下顺序检查,通常能较快找到问题:

  1. 使用 JSON.stringify(res) 获取完整的微信回调内容。
  2. 在浏览器调试工具中查看 /RenewPay/GetData 的原始响应。
  3. 确认传给 invoke() 的是对象,而不是字符串。
  4. 核对 appId、timeStamp、nonceStr、package、signType 和 paySign 的名称及大小写。
  5. 确认 package 的格式为 prepay_id=...。
  6. 检查统一下单使用的 appId、openid、商户号和前端 appId 是否属于同一套配置。
  7. 在服务端使用最终返回给前端的字段重新验算支付签名。
  8. 检查微信支付商户平台中的 JSAPI 支付授权目录。
  9. 确认页面通过实际生产域名在微信内置浏览器中访问。
  10. 查看服务端的统一下单响应和支付通知日志。

前端回调中的 get_brand_wcpay_request:ok 只能说明客户端支付流程返回成功,不能直接作为发货或续费依据。最终业务状态必须以后端验签后的支付通知为准,也可以通过服务端主动查询订单获得支付结果。

备注:内容仅供参考。