接口概述
一句话说明
ssl.cert 是「按域名查 HTTPS 证书到期时间」的接口:
传入域名与端口,服务端直连 https://域名:端口 完成 TLS 握手,
读取证书后返回生效时间、到期时间与距到期剩余天数。
不需要你在服务器上装 openssl,也不依赖第三方接口。
| 请求地址 | https://api.xujian.tech/openapi/ssl/cert |
|---|---|
| 请求方式 | GET(domain / port 放 Query String) |
| 鉴权方式 | 请求头 X-API-Key |
| 接口编码 | ssl.cert |
| 收费类型 | PER_CALL(按次计费,0.0100 元/次) |
| 计费特殊规则 | 取到证书才计费:域名为空、端口非法、连接超时、握手失败、
该端口未提供证书时,返回失败且不扣费;
证书已过期不算失败(返回 valid=false、天数为负),正常计费 |
| 响应格式 | JSON,Content-Type: application/json;charset=UTF-8 |
| 是否需要授权 | 否(无需授权,API Key 有效且余额充足即可调用) |
| 典型用途 | 证书到期巡检、到期告警、运维看板、批量域名体检 |
快速开始
# 查 api.xujian.tech 的 443 端口证书
curl -s -G "https://api.xujian.tech/openapi/ssl/cert" \
--data-urlencode "domain=api.xujian.tech" \
-H "X-API-Key: 你的APIKey"
# 自定义端口
curl -s -G "https://api.xujian.tech/openapi/ssl/cert" \
--data-urlencode "domain=api.xujian.tech" \
--data-urlencode "port=8443" \
-H "X-API-Key: 你的APIKey"
domain 怎么填
domain 是必填的域名,例如 api.xujian.tech。
写成 https://api.xujian.tech/path 这类带协议、带路径的形式也可以,
接口会自动剥成 api.xujian.tech。port 可选,不传默认 443;
域名后自带 :端口 时,以显式传入的 port 为准。
请求参数
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
X-API-Key | String | 是 | 开发者 API Key |
| 参数名 | 类型 | 必填 | 默认值 | 示例 | 说明 |
|---|---|---|---|---|---|
domain | String | 是 | — | api.xujian.tech | 域名;允许带协议与路径(自动剥离);为空返回失败且不计费 |
port | Integer | 否 | 443 | 443 | 端口,取值范围 1-65535;非 443 的 HTTPS 服务请显式传入 |
响应参数
业务字段
| 字段 | 类型 | 示例 | 说明 |
|---|---|---|---|
domain | String | api.xujian.tech | 域名(回显,已去掉协议与路径) |
port | Integer | 443 | 端口(回显) |
notBefore | String | 2026-09-28 08:00:00 | 证书生效时间(yyyy-MM-dd HH:mm:ss) |
notAfter | String | 2026-12-27 07:59:59 | 证书到期时间(yyyy-MM-dd HH:mm:ss) |
daysRemaining | Long | 59 | 距到期剩余天数(按自然日计算,负数表示已过期) |
valid | Boolean | true | 当前时间是否处于证书有效期内(false = 未生效或已过期) |
subject | String | api.xujian.tech | 证书主体 CN(通配证书形如 *.xujian.tech) |
issuer | String | R3 | 证书颁发机构 CN |
公共字段
| 字段 | 类型 | 说明 |
|---|---|---|
apiCode | String | 接口编码 ssl.cert |
apiName | String | 接口名称 |
chargeType | String | 计费类型 |
balance | BigDecimal | 调用完成后(已扣费)的账户余额(元) |
costMs | Long | 本次调用耗时(毫秒) |
口径与边界提示
① daysRemaining 按自然日计算(今天到期为 0,昨天到期为 -1),
不含具体时分,做告警时建议留 1 天余量;
② 结果取的是服务端返回的叶子证书(站点证书),不是中间证书 / 根证书;
③ 握手时已带 SNI,同 IP 部署多域名时能取到对应域名的证书;
④ 连接与握手共用 10 秒超时,超时按失败处理且不计费;
⑤ 证书已过期仍会返回结果(valid=false、天数为负),
这正是巡检场景需要的数据。
响应示例
成功(证书有效,code = 0)
{
"code": 0,
"msg": "success",
"data": {
"domain": "api.xujian.tech",
"port": 443,
"notBefore": "2026-09-28 08:00:00",
"notAfter": "2026-12-27 07:59:59",
"daysRemaining": 59,
"valid": true,
"subject": "api.xujian.tech",
"issuer": "R3",
"apiCode": "ssl.cert",
"apiName": "SSL 证书到期查询",
"chargeType": "PER_CALL",
"balance": 99.9900,
"costMs": 320
}
}
成功(证书已过期,valid = false,code = 0)
{
"code": 0,
"msg": "success",
"data": {
"domain": "expired.example.com",
"port": 443,
"notBefore": "2026-07-01 08:00:00",
"notAfter": "2026-10-01 07:59:59",
"daysRemaining": -28,
"valid": false,
"subject": "expired.example.com",
"issuer": "R3",
"apiCode": "ssl.cert",
"apiName": "SSL 证书到期查询",
"chargeType": "PER_CALL",
"balance": 99.9800,
"costMs": 290
}
}
失败(缺少 domain)—— 不收费
{
"code": 500,
"msg": "domain 不能为空(域名)",
"data": null
}
失败(连接不上 / 未取到证书)—— 不收费
{
"code": 500,
"msg": "无法连接或获取该域名的 SSL 证书,请确认域名、端口与 HTTPS 服务是否正常;本次调用不计费",
"data": null
}
错误码与常见失败原因
| code | msg(示例) | 处理建议 |
|---|---|---|
| 0 | success | 调用成功 |
| 500 | 缺少请求头 X-API-Key | 补充 X-API-Key |
| 500 | API Key 无效 / API Key 已停用 | 检查 Key 或重新启用 |
| 500 | 客户不存在或已停用 | 联系平台(可联系微信xujian_cq) |
| 500 | 接口不存在或已停用 | 确认 ssl.cert 当前是否维护中 |
| 500 | 余额不足,请先充值。可联系微信xujian_cq | 充值后重试,余额不足不扣费 |
| 500 | domain 不能为空(域名) | 补齐 domain;不计费 |
| 500 | domain 不合法,请传域名(如 api.xujian.tech) | 检查域名写法;不计费 |
| 500 | port 不合法(1-65535) | 端口取 1-65535;不计费 |
| 500 | 无法连接或获取该域名的 SSL 证书,请确认域名、端口与 HTTPS 服务是否正常;本次调用不计费 | 域名解析 / 防火墙 / 端口 / HTTPS 是否开启;不计费 |
| 500 | 该端口未提供 SSL 证书,请确认已启用 HTTPS;本次调用不计费 | 确认该端口是 HTTPS 服务;不计费 |
多语言代码示例
Java(Hutool)
String body = HttpRequest.get("https://api.xujian.tech/openapi/ssl/cert")
.form("domain", "api.xujian.tech")
.form("port", "443")
.header("X-API-Key", apiKey)
.timeout(15000)
.execute()
.body();
JSONObject json = JSONUtil.parseObj(body);
if (json.getInt("code") != 0) {
System.out.println("查询失败(不收费):" + json.getStr("msg"));
return;
}
JSONObject data = json.getJSONObject("data");
System.out.println("到期时间:" + data.getStr("notAfter"));
System.out.println("剩余天数:" + data.getLong("daysRemaining"));
System.out.println("是否有效:" + data.getBool("valid"));
Python
import requests
def get_ssl_cert(api_key: str, domain: str, port: int = 443) -> dict | None:
"""查域名证书到期信息;取不到证书返回 None 且不扣费"""
resp = requests.get(
"https://api.xujian.tech/openapi/ssl/cert",
params={"domain": domain, "port": port},
headers={"X-API-Key": api_key},
timeout=20,
)
result = resp.json()
if result.get("code") != 0:
print("查询失败(不收费):", result.get("msg"))
return None
return result["data"]
if __name__ == "__main__":
info = get_ssl_cert("你的APIKey", "api.xujian.tech")
if info:
print(info["notAfter"], info["daysRemaining"], info["valid"])
if info["daysRemaining"] < 30:
print("证书即将到期,尽快续期!")
JavaScript(浏览器 / Node 18+)
const params = new URLSearchParams({ domain: "api.xujian.tech", port: "443" });
const resp = await fetch(`https://api.xujian.tech/openapi/ssl/cert?${params}`, {
headers: { "X-API-Key": API_KEY },
});
const { code, msg, data } = await resp.json();
if (code === 0) {
console.log(data.notAfter, data.daysRemaining, data.valid);
} else {
console.warn("查询失败(不收费):", msg);
}
常见问题(FAQ)
ssl.cert 接口怎么收费?
ssl.cert 的收费类型为 PER_CALL(按次计费),当前单价 0.0100 元/次,调用前校验余额,余额不足返回「余额不足,请先充值。可联系微信xujian_cq」且不扣费;充值可可联系微信xujian_cq。扣费金额、交易前后余额均记录于交易流水中。
domain 必填吗?port 不传会怎样?
domain 必填;port 可选,不传默认 443。
域名允许写成 https://api.xujian.tech/path 这种带协议、带路径的形式,
会自动剥成 api.xujian.tech;域名后自带 :端口 时,
以显式传入的 port 为准。
daysRemaining 是怎么算的?
按自然日计算:到期日 - 今天。
今天到期为 0,昨天到期为 -1(同时 valid=false)。
做告警时建议留 1 天余量,例如 daysRemaining <= 30 触发续期提醒。
证书已过期还能查到吗?
可以。只要能完成 TLS 握手取到证书,即使已过期也会返回结果,
此时 valid=false、daysRemaining 为负数,
正好满足巡检与告警场景(这类结果正常计费,因为确实查到了)。
取不到证书会扣费吗?
不会。域名为空、端口非法、连接超时、握手失败、该端口未提供证书时, 返回失败且不扣费;只有真正取到证书才计一次费用(0.01 元)。
是自签证书 / 证书链不完整能查吗?
自签证书等不受信任的证书会导致握手校验失败,接口会返回失败且不计费。 请确认站点部署的是受信任 CA 签发的证书。
调用需要签名或加密吗?
不需要。XAPI 的接口仅校验请求头 X-API-Key,不做签名、时间戳或加密。