小米MIXR API无官方PHP SDK,需手写cURL调用RESTful接口,严格校验Authorization头、messages结构、token有效期及错误降级机制。

小米 MIXR API 不支持 PHP 原生 SDK,必须手写 HTTP 请求
小米目前没发布任何官方 PHP SDK,MIXR 服务只开放 RESTful API(HTTPS 接口),所有调用都得靠 curl 或 file_get_contents 发送带认证头的 POST 请求。别找 composer 包,也别搜 “MIXR php sdk”,不存在。
常见错误现象:cURL error 60: SSL certificate problem(本地开发环境未配置 CA 证书)、401 Unauthorized(Authorization 头格式错或 token 过期)、400 Bad Request(messages 字段结构不合法)。
- 必须用
POST方法,Content-Type: application/json - 请求头必须包含
Authorization: Bearer <your_access_token>,不是API-Key也不是X-API-Key - 接口地址是
https://api.xiaomi.com/mixr/v1/chat/completions(以小米控制台实际文档为准,路径可能微调) - token 需从小米开发者平台申请,且需开通 MIXR 服务权限,不是 MIUI 登录态 token
构造符合 MIXR 要求的 messages 数组结构
MIXR 的输入不是单条字符串,而是严格按角色分层的 messages 数组,类似 OpenAI 格式但不完全兼容。PHP 里必须用索引数组模拟 JSON 对象,否则会返回 "messages must be an array of objects"。
典型使用场景:客服对话上下文续聊,需保留历史轮次(最多 10 条),不能只传最新一句。
立即学习“PHP免费学习笔记(深入)”;
-
role只接受"user"、"assistant"、"system"三种字符串,大小写敏感,"User"会报错 -
content必须是字符串,不能是null或数字,空格字符串也不行(建议 trim 后校验) - system 消息只能放在最前面,且仅允许出现一次;重复或位置错会导致
422 Unprocessable Entity - 示例片段:
json
{
"model": "mixr-1.0",
"messages": [
{"role": "system", "content": "你是一个电商客服,回答要简洁,不提技术细节"},
{"role": "user", "content": "订单 123456 物流停更了,怎么回事?"},
{"role": "assistant", "content": "已为您查询,物流信息正在更新中,预计2小时内刷新。"}
],
"temperature": 0.3
}
PHP 中处理 access_token 刷新和有效期
小米 MIXR 的 access_token 默认 2 小时过期,且不提供自动刷新 endpoint。硬编码或写死在配置里,上线后必然中断。PHP 应用必须自己维护 token 生命周期。
容易踩的坑:file_get_contents 默认无超时,token 请求卡住会导致整个客服接口阻塞;缓存 token 到文件时没加锁,高并发下多个进程覆盖写入旧 token。
- 把 token 存到
/tmp/mixr_token.json比存在内存或 $_SESSION 更可靠(CLI/Swoole/FPM 共享) - 每次调用前先读文件,检查
expires_at时间戳是否早于time(),早于则重新请求https://api.xiaomi.com/oauth2/token - 刷新 token 的请求要用
client_id+client_secret+refresh_token(首次授权后获得),不是原 access_token - 写入新 token 文件时,先
file_put_contents($path . '.tmp', $json),再rename()原子替换,避免读到半截内容
生产环境必须加 fallback 和日志追踪
MIXR 接口不稳定是常态,尤其在流量高峰或模型版本切换时。PHP 客服系统不能因为一次 503 Service Unavailable 就返回空白或报错页面。
真实问题:用户问“退货流程”,接口超时,客服页面卡死,客服人员无法手动补回复。
- 设置
curl_setopt($ch, CURLOPT_TIMEOUT_MS, 8000),别用默认 0(无限等待) - 捕获
curl_error($ch)和curl_getinfo($ch, CURLINFO_HTTP_CODE),HTTP 状态码非 2xx 一律走降级逻辑 - 降级方案可以是预设话术数组(如“正在查询,请稍等”),或转人工按钮,别直接抛异常
- 每条请求必须记录 trace_id、request_body(脱敏手机号/订单号)、response_status、耗时,否则出问题根本没法对齐小米工单
最麻烦的其实是调试阶段——小米返回的错误信息藏在 response body 里,比如 {"error":{"code":"invalid_param","message":"messages[0].content cannot be empty"}},但很多人只看 HTTP 状态码就放弃排查了。











