调用 alipay.open.auth.token.app 接口时返回 404
结论
404 通常与 BizContent 里的授权参数无关,更可能是 DefaultAopClient 的网关地址配置有误。
DefaultAopClient 的第一个参数应填写支付宝开放平台的网关地址,不能填写具体 API 的方法路径。当前代码使用的是:
https://openapi.alipay.com/alipay.open.auth.token.app
这不是支付宝开放平台的标准网关路由,服务器会直接返回 HTTP 404。正确地址是:
https://openapi.alipay.com/gateway.do
AlipayOpenAuthTokenAppRequest 已经表示了 alipay.open.auth.token.app 方法。SDK 会将其作为 method 参数提交,无须再拼接到 URL 中。
正确的客户端配置
生产环境可以这样初始化:
IAopClient client = new DefaultAopClient(
"https://openapi.alipay.com/gateway.do",
aliPayInfo.AliPayAppId,
aliPayInfo.AlipayMerchantPrivateKey,
"json",
"1.0",
"RSA2",
aliPayInfo.AlipayPublicKey,
"UTF-8",
false
);
如果使用沙箱环境,应配置对应的沙箱网关,例如:
https://openapi-sandbox.dl.alipaydev.com/gateway.do
沙箱网关、沙箱应用 ID 和沙箱密钥必须配套使用,不能与生产环境的配置混用。具体地址还需以当前支付宝开放平台文档及所用 SDK 的说明为准。
支付宝 .NET SDK 的不同版本可能提供不同的 DefaultAopClient 构造函数重载。请根据项目实际引用的 SDK 确认参数顺序,特别是以下参数:
serverUrlappIdprivateKeyformatversionsignTypealipayPublicKeycharset
推荐的调用示例
可以通过对象序列化生成 BizContent,减少手工拼接 JSON 带来的转义和空值问题:
IAopClient client = new DefaultAopClient(
"https://openapi.alipay.com/gateway.do",
aliPayInfo.AliPayAppId,
aliPayInfo.AlipayMerchantPrivateKey,
"json",
"1.0",
"RSA2",
aliPayInfo.AlipayPublicKey,
"UTF-8",
false
);
AlipayOpenAuthTokenAppRequest request =
new AlipayOpenAuthTokenAppRequest();
if (!string.IsNullOrWhiteSpace(aliPayInfo.AppRefreshAuthToken))
{
request.BizContent = JsonConvert.SerializeObject(new
{
grant_type = "refresh_token",
refresh_token = aliPayInfo.AppRefreshAuthToken
});
}
else
{
request.BizContent = JsonConvert.SerializeObject(new
{
grant_type = "authorization_code",
code = aliPayInfo.AppAuthCode
});
}
AlipayOpenAuthTokenAppResponse response = client.Execute(request);
if (response == null)
{
throw new InvalidOperationException("支付宝接口未返回有效响应。");
}
if (!response.IsError)
{
string appAuthToken = response.AppAuthToken;
string appRefreshToken = response.AppRefreshToken;
}
else
{
string errorMessage =
$"支付宝接口调用失败,Code={response.Code}," +
$"SubCode={response.SubCode}," +
$"Msg={response.Msg},SubMsg={response.SubMsg}";
throw new InvalidOperationException(errorMessage);
}
示例中的 JsonConvert 来自 Newtonsoft.Json。如果项目使用 System.Text.Json,可以改为:
request.BizContent = JsonSerializer.Serialize(new
{
grant_type = "authorization_code",
code = aliPayInfo.AppAuthCode
});
原代码中还需要检查的问题
原来的条件判断是:
if (!string.IsNullOrEmpty(aliPayInfo.AppAuthToken))
但进入该分支后,代码实际使用的是:
aliPayInfo.AppRefreshAuthToken
刷新令牌时,应当判断 AppRefreshAuthToken:
if (!string.IsNullOrWhiteSpace(aliPayInfo.AppRefreshAuthToken))
否则可能出现 AppAuthToken 有值而 AppRefreshAuthToken 为空的情况。这个问题通常会让支付宝返回业务参数错误,而不是 HTTP 404,但同样需要修正。
授权码和刷新令牌也不能混用:
- 首次换取应用授权令牌时,
grant_type为authorization_code,并传入code。 - 刷新应用授权令牌时,
grant_type为refresh_token,并传入refresh_token。 - 授权码一般有时效限制,通常不能重复使用。
- 刷新令牌应使用接口返回的
app_refresh_token对应值。
如何区分网关错误和业务错误
HTTP 404 表示请求没有正常进入支付宝开放平台的 API 网关处理流程,应先检查 URL、代理及网络转发配置。
网关地址修正后,如果签名、授权码或业务参数有误,通常会收到支付宝 API 的响应,其中包含:
code
msg
sub_code
sub_msg
这属于业务或签名错误,需要根据 sub_code 和 sub_msg 继续排查,而不是继续检查 HTTP 路由。
如果改为 /gateway.do 后仍返回 404,可以依次检查:
- 实际运行时的
serverUrl是否被配置文件或环境变量覆盖。 - 反向代理、网关或抓包代理是否改写了请求地址。
- 生产环境与沙箱环境是否混用。
- SDK 版本对应的
DefaultAopClient构造函数参数顺序是否正确。 - 请求日志中的最终 URL 是否确实指向
/gateway.do。 - 是否绕过 SDK 手工拼接了 API 方法路径。
本次需要修改的是网关地址:将具体接口路径替换为统一网关地址,再由 SDK 通过 AlipayOpenAuthTokenAppRequest 提交 alipay.open.auth.token.app 方法。
备注:内容仅供参考。
