PAYATHON 2026

网页调取支付二维码提示ACQ.MERCHANT_STATUS_NOT_NORMAL

支付老李

结论

ACQ.MERCHANT_STATUS_NOT_NORMAL 表示支付宝受理当前交易时,认为实际参与收款的商户处于不可用状态。

后台显示签约正常,并不能排除这个问题。签约状态通常只能说明某个产品或应用已完成签约,不代表当前请求中的 app_id、商户账号、收款主体、服务商代调用关系和交易产品权限完全匹配。

排查时优先核对以下内容:

  • 请求中的 app_id 是否属于已签约且可以正常收款的应用;
  • 应用绑定的支付宝商户账号是否正常;
  • 当前接口对应的产品能力是否已经生效;
  • 服务商模式下,被代调用商户是否已完成授权并具备收款资格;
  • 是否混用了沙箱、旧应用、旧密钥或其他商户的配置。

常见原因

app_id 与签约商户不一致

这是常见的配置问题。例如,商户后台显示已经签约“当面付”,但程序实际使用的是另一个应用的 app_id。支付宝会根据请求中的应用身份检查商户状态,不会根据操作人员当前登录后台所看到的商户进行判断。

常见情况有:

  • 测试环境和生产环境的配置混用;
  • 多个支付宝应用共用同一套配置文件;
  • 更换应用后只替换了密钥,没有替换 app_id;
  • 使用服务商应用的 app_id,却没有按服务商代调用方式传递商户授权信息;
  • 后台查看的是商户 A,程序调用的却是商户 B 的应用。

产品签约正常,但尚未生效或能力不匹配

签约状态需要和实际调用的 API 对应。生成线下扫码支付二维码通常会调用 alipay.trade.precreate。如果应用只开通了其他支付产品,或者相关产品能力尚未绑定到当前应用,调用仍可能失败。

除了产品列表中的状态,还要检查签约主体、应用和产品之间的关联关系。

商户账号或收款能力受到限制

商户账号可能可以正常登录,签约页面也可能显示正常,但交易能力仍会受到以下情况影响:

  • 商户认证信息失效或需要补充;
  • 商户经营状态发生变化;
  • 收款权限受到风控限制;
  • 商户账号存在待处理的审核;
  • 接口对应的业务能力被暂停;
  • 服务商下的被代调用商户状态异常。

这些限制不一定会显示在普通签约列表中,需要查看支付宝商家平台的通知和风控提示,必要时请支付宝技术支持确认。

服务商代调用参数错误

如果系统通过服务商应用为其他商户发起交易,需要确认代调用关系仍然有效。常见问题有:

  • 商户授权已过期或被撤销;
  • app_auth_token 属于另一商户;
  • 传入了错误的 app_auth_token;
  • 被代调用商户没有开通对应产品;
  • 服务商应用与商户授权关系不匹配;
  • 直连商户场景误传了服务商相关参数。

服务商自身状态正常,不代表被代调用商户也具备交易资格。

网关、环境或密钥配置混用

沙箱应用、生产应用及其密钥不能混用。密钥错误通常会触发验签或权限类错误,但运行环境配置错误也可能让请求使用非预期的应用和商户身份,最终出现商户状态异常。

需要一起核对:

  • 支付宝网关地址;
  • app_id;
  • 应用私钥;
  • 支付宝公钥或支付宝公钥证书;
  • 应用证书及支付宝根证书;
  • app_auth_token;
  • 配置文件实际加载的环境。

排查步骤

1. 保存支付宝返回的完整响应

不要只记录异常框架包装后的这一行:

ERROR_GATEWAY: Get Alipay API Error:Business Failed - ACQ.MERCHANT_STATUS_NOT_NORMAL

还要保存支付宝原始响应中的以下字段:

code
msg
sub_code
sub_msg
request_id

如果 SDK 可以取得请求参数,也应记录:

app_id
method
sign_type
timestamp
app_auth_token 是否存在

日志中不要输出应用私钥、完整授权令牌或其他敏感信息。

2. 确认实际请求身份

从运行时日志中获取真实的 app_id,然后到支付宝开放平台查找对应应用,确认:

  • 应用所属账号是否为预期的收款商户;
  • 应用是否已经上线;
  • 当前应用是否具备所调用 API 对应的产品能力;
  • 应用状态和商户状态是否正常;
  • 程序是否读取了旧配置或其他环境变量。

不要只根据代码仓库中的配置文件判断。容器环境变量、配置中心和启动参数都可能覆盖本地配置。

3. 核对调用的 API 和签约产品

如果请求方法是:

alipay.trade.precreate

应检查当前应用和商户是否具备对应的扫码支付能力。如果实际调用的是其他 API,则要根据该 API 所属的产品重新检查权限。

还要确认请求是通过正确的应用发出的。同一商户名下的其他应用已经签约,并不意味着当前 app_id 会自动获得相同能力。

4. 区分直连商户与服务商模式

直连商户通常通过自己的应用直接收款。服务商模式则可能使用服务商应用,并携带商户授权信息。

如果请求中有 app_auth_token,需要确认:

  1. 令牌对应的是哪一个授权商户;
  2. 授权是否仍然有效;
  3. 授权范围是否包含当前调用的接口;
  4. 该商户是否已经开通对应的支付产品;
  5. 缓存中的令牌是否误用了另一商户的值。

可以临时记录授权令牌的摘要值,例如哈希值或前后少量字符,不要记录完整令牌。

5. 使用最小请求直接测试

排除业务系统中的配置覆盖和参数拼装问题后,可以使用支付宝官方 SDK 构造一个最小请求。下面的示例只用于说明排查方法,具体的 SDK 版本、构造方式和证书模式应以项目当前依赖为准。

AlipayClient alipayClient = new DefaultAlipayClient(
    "https://openapi.alipay.com/gateway.do",
    appId,
    merchantPrivateKey,
    "json",
    "UTF-8",
    alipayPublicKey,
    "RSA2"
);

AlipayTradePrecreateRequest request =
    new AlipayTradePrecreateRequest();

request.setBizContent("""
{
  "out_trade_no": "TEST_202609130001",
  "total_amount": "0.01",
  "subject": "支付接口测试"
}
""");

AlipayTradePrecreateResponse response =
    alipayClient.execute(request);

System.out.println("code=" + response.getCode());
System.out.println("msg=" + response.getMsg());
System.out.println("subCode=" + response.getSubCode());
System.out.println("subMsg=" + response.getSubMsg());

服务商代调用时,通常还需要在调用中传入商户授权令牌。例如:

AlipayTradePrecreateResponse response =
    alipayClient.execute(request, appAuthToken);

不要为了测试随意添加 app_auth_token。是否需要这个参数取决于接入模式。令牌传错后,支付宝会按照错误的商户身份处理请求。

6. 与可用请求逐项对比

如果其他环境或其他商户可以正常生成二维码,可以逐项比较以下内容:

gateway
app_id
method
sign_type
notify_url
app_auth_token 是否传递
授权商户身份
产品签约主体
应用上线状态

对比范围不要只限于业务参数。out_trade_no、金额和标题通常不会导致 MERCHANT_STATUS_NOT_NORMAL,应优先检查应用和商户身份。

7. 提交支付宝侧核查

如果应用、产品、授权关系和环境配置均已确认无误,但错误仍能稳定复现,需要请支付宝技术支持核查。建议提交:

  • 完整的 sub_code 和 sub_msg;
  • 支付宝返回的 request_id;
  • 精确到秒的请求时间;
  • 使用的 app_id;
  • 调用的 API 名称;
  • 是否属于服务商代调用;
  • 被代调用商户的支付宝商户号或 PID;
  • 脱敏后的请求参数;
  • 商家平台显示签约正常的截图。

商户状态和风控限制属于支付宝服务端信息,仅凭客户端返回的错误通常无法确定具体原因。支付宝可通过 request_id 定位对应请求。

建议的日志处理

可以在统一的支付异常处理逻辑中保留诊断字段:

try {
    AlipayTradePrecreateResponse response =
        alipayClient.execute(request, appAuthToken);

    if (!response.isSuccess()) {
        log.error(
            "Alipay precreate failed: appId={}, code={}, msg={}, subCode={}, subMsg={}, requestId={}",
            appId,
            response.getCode(),
            response.getMsg(),
            response.getSubCode(),
            response.getSubMsg(),
            response.getRequestId()
        );
    }
} catch (AlipayApiException e) {
    log.error(
        "Alipay API exception: appId={}, message={}",
        appId,
        e.getMessage(),
        e
    );
}

直连模式应调用不带 appAuthToken 的重载方法。能否直接取得示例中的字段,取决于项目使用的支付宝 SDK 版本。如果某个 getter 不存在,应从 SDK 提供的原始响应对象或响应正文中读取,不要自行补造字段。

注意事项

  • 签约正常,不代表当前请求使用的应用和商户状态正常。
  • 优先检查运行时使用的 app_id 和 app_auth_token,不要只看后台页面。
  • 反复更换订单号或金额通常无法解决这个错误,因为它一般与订单业务参数无关。
  • 不要在日志、截图或工单中暴露应用私钥、完整 app_auth_token、证书私钥等敏感信息。
  • 如果只有部分商户失败,优先检查被代调用商户的授权状态和收款资格。
  • 如果所有商户同时失败,优先检查服务商应用、产品权限、生产配置和网关环境。
  • 如果错误突然出现,近期又没有代码变更,应检查商户通知、认证状态、授权有效期和平台侧限制,并携带 request_id 联系支付宝核查。

备注:内容仅供参考。