Oracle AI Service REST API 调用必须严格设置 Authorization(Bearer JWT Token)和 Content-Type(application/json),不可复用 oci8 数据库连接,需独立构造请求体并遵循 TLS 1.2+ 和指数退避轮询规范。

Oracle AI Service 的 REST API 调用必须带 Authorization 和 Content-Type
PHP 里用 curl 或 file_get_contents 调 Oracle AI Service(如 Document Understanding、Anomaly Detection)的 API 时,90% 的 401 Unauthorized 或 400 Bad Request 都是因为头信息漏了或写错了。
Oracle AI Service 不接受 Basic Auth,必须用 OCI 签名(推荐用 SDK)或短期有效的 bearer token(来自 Resource Principal 或 API Key)。但开发阶段最简路径是:先用 OCI CLI 获取临时 token:
oci auth print-oci-cli-rc --profile DEFAULT
然后在 PHP 中显式带上:
-
Authorization: Bearer <your-jwt-token>(注意是Bearer,不是Bearer:或token) -
Content-Type: application/json(哪怕 POST 空 body 也要设) -
opc-request-id: <uuid>(可选但建议加,便于排查)
PHP 连接 Oracle 数据库后,不能直接把 $conn 传给 AI Service
Oracle AI Service 是独立云服务,和本地/DBCS 上的 Oracle 数据库实例没有自动上下文关联。你不能指望 oci_connect() 返回的连接资源能“透传”到 AI Service 做语义理解或 SQL 生成。
立即学习“PHP免费学习笔记(深入)”;
真实链路是:PHP 从数据库查出数据 → 组装成 JSON 或 base64 编码的文档(如 PDF、OCR 文本、表格 CSV)→ POST 到 AI Service 对应 endpoint(如 /20230701/actions/analyzeDocument)。
常见误操作:
- 试图用
oci_execute()直接调用 AI Service 的 PL/SQL 封装 —— OCI 不提供该能力,服务端无对应包 - 把数据库连接字符串当 API endpoint 用 —— 比如把
localhost:1521/XE拼进https://<region>.ai.oci.oraclecloud.com,必然 DNS 失败 - 把查询结果数组直接
json_encode()后 POST,却不检查字段名是否符合 AI Service 的 schema 要求(例如 Document Understanding 要求document字段是 base64 string)
oci8 扩展与 Oracle AI Service 的 TLS 兼容性问题
PHP 的 oci8 扩展只管连 Oracle DB,但它依赖的 Oracle Instant Client 版本会影响整个进程的 OpenSSL 行为。如果服务器上 Instant Client 是 19c 旧版,而 AI Service 的 endpoint(如 us-ashburn-ai.oci.oraclecloud.com)强制 TLS 1.2+,PHP 可能静默失败(curl 报 SSL routines:ssl3_get_record:wrong version number)。
验证方式:
php -r "print_r(openssl_get_cipher_methods());"
若输出为空或不含 TLSv1.2,说明底层 OpenSSL 不匹配。解决办法只有两个:
- 升级 Oracle Instant Client 至 21c,并确保其链接系统 OpenSSL 1.1.1+(非系统自带的旧版)
- 绕过 oci8 的 TLS 影响:AI Service 调用统一改用纯 PHP+cURL,不复用 oci8 的 SSL 上下文
别碰 openssl.cafile 或 curl.cainfo 临时覆盖——OCI 证书链经常更新,硬编码路径会突然失效。
异步任务状态轮询别用 sleep(1) 硬等
Oracle AI Service 的多数分析接口(如 analyzeDocument)返回 202 Accepted + opc-work-request-id,后续要 GET /20230701/workRequests/{id} 查状态。新手常写:
do { $res = file_get_contents($status_url); sleep(1); } while ($res['status'] !== 'SUCCEEDED');
这会快速触发 OCI 的速率限制(默认 10 次/秒),且没处理 FAILED 或 CANCELLED 状态。
正确做法:
- 初始等待至少 3 秒,之后按指数退避:第 1 次等 3s,第 2 次等 6s,第 3 次等 12s……上限 60s
- 每次 GET 必须带
Authorization,且检查响应头opc-retry-after(OCI 可能主动建议下次轮询时间) - 累计轮询超 5 分钟直接中断,记录
opc-work-request-id供人工查 OCI Console
真正难的不是调通,而是让 PHP 进程在长轮询中不被 Apache 超时杀掉、不卡住 FPM worker、不漏掉失败回调——这些得结合 set_time_limit(0)、ignore_user_abort(true) 和日志埋点一起看。



















