PAYATHON 2026

Alipay Payment Gateway 报错 ILLEGAL_PARTNER_EXTERFACE

支付小周

结论

ILLEGAL_PARTNER_EXTERFACE 通常与 Django、支付表单或 payment_type 本身无关。这个错误表示支付宝认为当前商户没有权限调用请求中的支付接口。

建议先检查以下三项:

  1. 商户账号是否已签约并开通目标接口,例如旧版即时到账接口 create_direct_pay_by_user。
  2. 网关、商户身份和接口参数是否属于同一环境,沙箱配置与生产配置不能混用。
  3. 是否混用了旧版 Partner 接口与新版 OpenAPI 的 app_id、密钥或网关。

只修改 payment_type 通常无法解决接口权限问题。在旧版即时到账接口中,payment_type 一般为 1。沙箱和生产环境的区别主要在于网关地址、账号凭据、接口授权和签名配置,并不是换一个 payment_type 就能解决。

错误原因

EXTERFACE 是支付宝历史返回值中的拼写,应按原样识别。ILLEGAL_PARTNER_EXTERFACE 通常表示 Partner 没有目标接口的访问权限。

常见原因有:

  • 请求使用了 create_direct_pay_by_user,但商户账号没有签约即时到账产品。
  • 使用沙箱账号请求生产网关,或者使用生产 Partner 请求沙箱网关。
  • 代码示例使用旧版 Partner API,但账号只开通了新版当面付、电脑网站支付或手机网站支付产品。
  • service 参数指定了账号未开通的接口。
  • 合作伙伴身份参数有误,例如 partner、seller_id 或收款账号填写错误。
  • 签约主体、收款主体与请求中的商户身份不一致。
  • 已签约产品尚未生效,或者商户后台显示的产品能力与代码调用的 API 不一致。

签名有误时,支付宝一般会返回签名相关的错误。因此,收到 ILLEGAL_PARTNER_EXTERFACE 后,应先排查接口权限和环境配置是否对应。

解决步骤

1. 确认实际调用的接口

检查提交给支付宝的参数,尤其是 service:

service=create_direct_pay_by_user

这个值对应旧版即时到账接口,当前 Partner 必须已开通该产品。即使商户开通了其他支付宝支付产品,也不会自动获得这个接口的调用权限。

如果接入的是新版电脑网站支付,通常应使用:

alipay.trade.page.pay

新版接口使用 app_id 和 RSA/RSA2 签名,不再采用旧版 partner + key 的 MD5 接入方式。两套协议的参数不能混用。

2. 检查环境是否完整匹配

同一次请求使用的所有配置都必须来自同一环境:

配置项必须保持一致
Gateway沙箱网关或生产网关
商户身份对应环境的 partner 或 app_id
密钥对应应用和环境的密钥
接口权限对应账号已开通的产品
回调地址当前环境可以访问的地址

不能只替换 Gateway,却继续使用另一个环境的账号或密钥。

支付宝平台可能调整具体网关地址和沙箱能力,应以当前支付宝开放平台控制台中的配置为准,不要直接照搬多年前的示例地址。

3. 核对旧版请求参数

旧版即时到账请求通常包含以下参数:

params = {
    "service": "create_direct_pay_by_user",
    "partner": ALIPAY_PARTNER,
    "_input_charset": "utf-8",
    "payment_type": "1",
    "notify_url": notify_url,
    "return_url": return_url,
    "seller_id": ALIPAY_PARTNER,
    "out_trade_no": order_no,
    "subject": subject,
    "total_fee": amount,
}

其中,payment_type 一般是字符串 "1"。但即使所有参数都填写正确,只要 ALIPAY_PARTNER 没有 create_direct_pay_by_user 权限,支付宝仍会返回 ILLEGAL_PARTNER_EXTERFACE。

还要确认:

partner == 已签约接口的合作伙伴 ID
seller_id == 实际收款主体

部分历史接口支持卖家邮箱参数,但在没有弄清账号配置前,不要混用 seller_id、seller_email 和 Partner ID。

4. 在商户后台确认产品权限

登录对应的商户账号或开放平台账号,逐项检查:

  • 已签约产品的准确名称;
  • 产品状态是否有效;
  • 产品对应的 API 名称;
  • 应用是否已绑定该产品能力;
  • 当前请求使用的是沙箱应用还是生产应用。

如果后台找不到目标接口的签约入口,可能是该历史产品已不再向新商户开放。此时应改用当前可以申请的电脑网站支付接口,不必继续调整旧版参数。

商户接口权限无法通过代码绕过。如果后台配置正确,但接口仍返回该错误,需要向支付宝技术支持提供 partner 或 app_id、接口名、请求时间和支付宝返回的请求标识,请其核查权限状态。工单和日志中不要提交商户私钥。

Django 中的推荐接入方式

新建的 Django 项目更适合使用支付宝 OpenAPI 的电脑网站支付接口 alipay.trade.page.pay。Python 社区常用的选择是 python-alipay-sdk,不过名称相近的包较多。安装前应核对源码地址、维护状态和文档,避免安装错误的同名包。

下面的代码采用常见的 SDK 接口形式。不同版本的初始化参数可能不同,请以实际安装版本的文档为准:

from alipay import AliPay
from django.conf import settings
from django.http import HttpResponseRedirect


alipay = AliPay(
    appid=settings.ALIPAY_APP_ID,
    app_notify_url=settings.ALIPAY_NOTIFY_URL,
    app_private_key_string=settings.ALIPAY_APP_PRIVATE_KEY,
    alipay_public_key_string=settings.ALIPAY_PUBLIC_KEY,
    sign_type="RSA2",
    debug=settings.ALIPAY_DEBUG,
)


def create_payment(request, order_no):
    order = get_order_and_check_owner(order_no, request.user)

    order_string = alipay.api_alipay_trade_page_pay(
        out_trade_no=order.number,
        total_amount=f"{order.amount:.2f}",
        subject=order.subject,
        return_url=settings.ALIPAY_RETURN_URL,
        notify_url=settings.ALIPAY_NOTIFY_URL,
    )

    gateway = (
        settings.ALIPAY_SANDBOX_GATEWAY
        if settings.ALIPAY_DEBUG
        else settings.ALIPAY_PRODUCTION_GATEWAY
    )

    return HttpResponseRedirect(f"{gateway}?{order_string}")

不要根据 debug 自行推测网关地址。建议在配置中明确保存控制台或 SDK 文档提供的地址:

# settings.py

ALIPAY_APP_ID = "your-app-id"
ALIPAY_DEBUG = True

ALIPAY_SANDBOX_GATEWAY = "sandbox-gateway-from-current-documentation"
ALIPAY_PRODUCTION_GATEWAY = "production-gateway-from-current-documentation"

私钥不应直接提交到 Git 仓库,可以通过环境变量或密钥管理服务加载。

异步通知验证

不能仅凭浏览器跳转到 return_url 就认定支付成功。服务器应通过 notify_url 接收支付宝通知,完成验签并核对金额和订单号后,再更新订单状态。

from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt


@csrf_exempt
def alipay_notify(request):
    data = request.POST.dict()
    signature = data.pop("sign", None)

    if not signature or not alipay.verify(data, signature):
        return HttpResponse("failure")

    order_no = data.get("out_trade_no")
    trade_status = data.get("trade_status")
    total_amount = data.get("total_amount")

    order = get_order_for_update(order_no)

    if not amount_matches(order.amount, total_amount):
        return HttpResponse("failure")

    if trade_status in {"TRADE_SUCCESS", "TRADE_FINISHED"}:
        mark_order_paid_idempotently(order, data.get("trade_no"))

    return HttpResponse("success")

生产代码还需要校验通知中的 app_id、收款方身份、订单币种等字段,并通过数据库事务和幂等逻辑处理重复通知,避免重复入账。

注意事项

  • payment_type="1" 只是特定旧接口中的业务参数,不代表商户拥有该接口的调用权限。
  • 不要混用旧版 MD5 Partner API 的 partner、key 与新版 RSA2 OpenAPI 的 app_id、应用私钥。
  • return_url 是用户浏览器的跳转地址,不能作为判断支付成功的唯一依据。
  • notify_url 必须能被支付宝服务器访问,本机 localhost 地址通常无法接收通知。
  • 金额应使用 Decimal,不要直接用二进制浮点数计算订单金额。
  • 日志可以记录接口名、订单号、运行环境和支付宝请求标识,但不能记录私钥、完整签名材料或其他敏感凭据。
  • 如果项目依赖的工具包只支持 create_direct_pay_by_user,而商户实际开通的是 alipay.trade.page.pay,应更换或升级工具包,不要继续修改 payment_type。

备注:内容仅供参考。