支付宝账单下载出现 UnknownHostException 如何解决?
结论
java.net.UnknownHostException: dwbillcenter-2-1-1.daily.alipay.net 表明服务器无法通过 DNS 解析下载地址中的主机名。异常发生在 HTTP 连接建立之前,通常与下载地址是否超过 30 秒无关。
域名中的 daily.alipay.net 很可能属于支付宝的测试、沙箱或内部环境,公网服务器通常无法直接解析或访问。排查时应先确认账单下载地址的来源、支付宝网关配置,以及应用环境是否混用,而不是延长超时时间。
为什么不是下载超时
下载地址的有效期与网络请求超时不是一回事:
- 地址有效期决定支付宝是否接受下载请求。
UnknownHostException表示 DNS 解析失败,此时客户端还没有连接到支付宝服务器。- 如果地址已经失效,通常会收到 HTTP 响应或业务错误,而不是
UnknownHostException。 - 调大
connectTimeout或readTimeout无法解决域名解析失败。
异常中最需要关注的是:
java.net.UnknownHostException: dwbillcenter-2-1-1.daily.alipay.net
需要查清 dwbillcenter-2-1-1.daily.alipay.net 为什么会出现在接口返回结果中,同时确认程序的运行环境能否解析这个域名。
排查步骤
1. 检查支付宝网关配置
先确认获取账单下载地址时使用的是生产网关还是沙箱网关。
生产环境通常配置为:
https://openapi.alipay.com/gateway.do
沙箱环境通常使用:
https://openapi.alipaydev.com/gateway.do
如果应用、公钥、私钥和网关分属不同环境,接口可能返回异常地址,行为也可能与预期不符。以下配置应属于同一套环境:
appId- 支付宝网关地址
- 应用私钥
- 支付宝公钥或支付宝公钥证书
- 应用公钥证书
- 支付宝根证书
- 账单所属账号
不要只改网关地址,也不要把沙箱密钥用于生产环境。
2. 记录接口返回的原始下载地址
获取账单地址后,在做好脱敏的前提下记录以下信息:
- 调用的支付宝网关
appIdbill_typebill_date- 接口响应码和子响应码
- 返回下载地址的 host
- 请求和响应时间
Java 中可以单独提取 host:
import java.net.URI;
String downloadUrl = billDownloadUrl;
URI uri = URI.create(downloadUrl);
System.out.println("scheme = " + uri.getScheme());
System.out.println("host = " + uri.getHost());
如果接口直接返回 *.daily.alipay.net,说明这个地址不是下载代码拼接出来的。此时应继续核对调用环境,必要时把请求日志和支付宝接口响应提交给支付宝技术支持确认。
3. 检查是否自行拼接或改写了下载地址
账单接口返回的下载地址一般应当作为完整 URL 直接使用,不要进行以下处理:
- 自行替换域名
- 手工拼接 path 和查询参数
- 对整个 URL 重复进行 URL 编码
- 删除或重新排序查询参数
- 通过配置文件覆盖返回地址的 host
- 将生产地址转换成测试地址
下载 URL 往往带有临时授权参数。直接把 daily.alipay.net 换成其他域名并不可靠,还可能导致签名或授权校验失败。
4. 在实际运行服务器上检查 DNS
DNS 检查应在发生异常的服务器或容器中执行,不能只在开发电脑上测试:
nslookup dwbillcenter-2-1-1.daily.alipay.net
也可以使用:
dig dwbillcenter-2-1-1.daily.alipay.net
如果查询不到 IP 地址,结果就与 UnknownHostException 相符。还需要检查:
/etc/resolv.conf中的 DNS 配置- 容器或 Kubernetes Pod 的 DNS 配置
- CoreDNS 是否正常
- 企业网络是否拦截外部 DNS
- HTTP 代理是否配置正确
- JVM 是否缓存了旧的 DNS 结果
对于 daily.alipay.net 这类疑似非公网环境的域名,不建议修改 hosts 文件并强行绑定 IP。IP 可能发生变化,即使建立了连接,后续仍可能因为 TLS 证书、路由或访问权限而失败。
5. 确认沙箱是否支持所需账单场景
如果当前使用沙箱网关,需要确认沙箱是否支持对应的账单下载能力和账单数据。不同接口和业务场景的沙箱支持范围可能不同,接口返回成功并不代表下载地址一定能从公网访问。
如果沙箱返回了 daily.alipay.net 地址,而业务最终需要下载真实账单,通常应改用配置完整的生产应用进行验证。是否属于支付宝侧的环境问题,应以当前接口文档和支付宝技术支持的确认结果为准。
推荐的下载实现
下载地址有时效性,获取成功后应立即使用,并为连接和读取设置合理的超时时间。下面使用 JDK 11 的 HttpClient:
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Path;
import java.time.Duration;
public class AlipayBillDownloader {
public static void download(String downloadUrl, Path target)
throws IOException, InterruptedException {
URI uri = URI.create(downloadUrl);
if (!"https".equalsIgnoreCase(uri.getScheme())) {
throw new IllegalArgumentException("Unexpected URL scheme");
}
if (uri.getHost() == null || uri.getHost().isBlank()) {
throw new IllegalArgumentException("Invalid download URL");
}
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10))
.followRedirects(HttpClient.Redirect.NORMAL)
.build();
HttpRequest request = HttpRequest.newBuilder(uri)
.timeout(Duration.ofSeconds(30))
.GET()
.build();
HttpResponse<Path> response = client.send(
request,
HttpResponse.BodyHandlers.ofFile(target)
);
if (response.statusCode() < 200 || response.statusCode() >= 300) {
throw new IOException(
"Download failed, HTTP status = " + response.statusCode()
);
}
}
}
调用时使用账单接口刚刚返回的完整 URL:
String downloadUrl = response.getBillDownloadUrl();
AlipayBillDownloader.download(
downloadUrl,
Path.of("/data/alipay-bill.zip")
);
实际文件可能是压缩包、文本或其他账单格式,不能仅凭业务描述中的“Excel”判断文件类型。具体处理方式应结合响应头、接口文档和实际文件内容确定。
针对 UnknownHostException 的异常处理
可以单独捕获 DNS 解析异常,将它与地址失效或 HTTP 错误区分开:
import java.net.UnknownHostException;
try {
AlipayBillDownloader.download(downloadUrl, target);
} catch (UnknownHostException e) {
throw new IllegalStateException(
"账单下载域名无法解析,请检查支付宝环境配置和服务器 DNS。host="
+ URI.create(downloadUrl).getHost(),
e
);
}
捕获到该异常后,不要针对同一个异常域名进行高频重试。DNS 无法解析时,短时间内反复请求通常没有意义。可以按以下顺序处理:
- 重新核对网关和应用环境。
- 必要时重新调用账单下载地址查询接口。
- 检查新地址的 host 是否仍为
daily.alipay.net。 - 如果持续返回同类地址,保留接口响应、请求时间和支付宝请求标识,并联系支付宝技术支持。
注意事项
- 不要在日志中输出完整的临时下载 URL,其中可能含有敏感授权参数。
- 下载地址获取后应立即使用,不要放入队列长时间等待。
- 不要试图通过延长 HTTP 超时解决
UnknownHostException。 - 不要自行替换支付宝返回 URL 中的域名。
- 不要使用固定 IP 或
hosts配置绕过 DNS。 - 生产与沙箱的网关、应用和密钥必须配套使用。
- 如果生产网关仍返回
daily.alipay.net,并且应用没有改写 URL,应将其视为异常响应,携带脱敏后的请求参数、响应内容和请求标识向支付宝核实。
备注:内容仅供参考。
