第三方对接指南
一页看懂,5 步完成 UserMatrix 对接。附带可运行的完整 demo。
流程一览
你的应用 UserMatrix 用户
│ │ │
│── 1. 构造登录链接 ─────────→│ │
│ │── 2. 跳转授权页 ───────→│
│ │←── 3. 用户扫码/授权 ────│
│←── 4. 带 code 回调 ────────│ │
│── 5. code 换用户信息 ─────→│ │
│←── 返回 openid+token ──────│ │
│ │ │
└─ 登录完成,后续用 token 调 API
扫码登录有「直接图片」与「后端跳转」两种呈现方式,最终都走同一套 act=callback 换用户信息。下文以**直接图片(推荐)**为主线;后端跳转写法在文末 Demo 以兼容形式保留。
准备材料
在 um.yunjii.cn/console/apps 创建应用,获得:
| 材料 | 说明 | 示例 |
|---|---|---|
appid | 应用 ID | 1001 |
appkey | 应用密钥(切勿泄露) | a3f8b2c9d1e7... |
| 回调域名 | 你的回调地址域名 | yourapp.com |
选择对接范式(先读这节)
UM 扫码登录有 三种 对接方式,速度、兼容性、前端改动量差别很大。新接入推荐 A(直接图片);老系统可继续用 B(后端跳转)兼容;C(iframe 嵌入)已淘汰,请勿再用。
| 维度 | A. 直接图片(推荐) | B. 后端跳转(兼容) | C. iframe 嵌入(已淘汰) |
|---|---|---|---|
| 核心做法 | <img src="api/qrcode.php"> 直接出图,前端轮询 query.php 拿登录态 | 后端调 connect.php?act=login 拿跳转 URL,再 302 到微信授权页 | 页面嵌 <iframe src=".../wxqrcode.php">,由 iframe 内完成授权 |
| 请求链路 | 1 次出图 + 轮询(纯前端,无你方后端参与) | 你方后端 1 次往返 UM + 浏览器跳第三方 | iframe 文档加载 + 内部多次跳转 |
| 速度 | ⚡⚡⚡ 最快:无后端往返、无 iframe 沙箱,UM 本地生成二维码 | ⚡⚡ 多一次后端往返 + 第三方 302 | 🐢 最慢,且第三方授权页常被 X-Frame-Options / CSP 拦截 → 扫码失败 |
| 外部依赖 | 无(UM 服务端本地生成 PNG) | 无 | 依赖被嵌套页,且受第三方嵌套策略限制 |
| 兼容性 | 所有现代浏览器 | 所有浏览器(含老系统、移动端 H5) | ❌ 微信/支付宝等授权页禁止被 iframe 嵌套,PC 端基本不可用 |
| 前端改动 | 需写轮询逻辑(约 20 行 JS) | 只需一个跳转链接(后端改) | 几乎零改动(但换来不可用) |
| 适用场景 | 新项目、SPA、自定义登录弹窗 | 服务端渲染页、不便改前端的老系统 | ——(不推荐) |
| 推荐度 | 强烈推荐 ★★★★★ | 老系统兼容 ★★★☆☆ | 请勿使用 ☆ |
三种方式最终都走同一套
act=callback换用户信息,区别只在"如何把二维码/授权页呈现给用户"。 实测参考:UM 服务端两个端点 TTFB 均在 ~0.1s(api/qrcode.php0.095s /connect.php?act=login0.107s),瓶颈不在服务端,而在前端流程与第三方嵌套限制——这正是 A 快、C 慢且易失败的根本原因。
30 秒选型
- 🆕 新接入 / 想最快最稳 → 用 A,照下面第 1 步开始。
- 🔧 老系统、后端拿 URL 再 302 最省事 → 用 B,见文末兼容写法。
- 🚫 任何新需求都不要再用 C(iframe 嵌入)。
下文第 1 步默认按 A(直接图片) 讲解;B 的写法在「完整 PHP Demo」里以兼容注释保留,老系统可直接复用。
5 步对接
接口:GET https://um.yunjii.cn/php/api/qrcode.php
直接把该接口作为 <img> 的 src,即可在页面显示登录二维码——无需 iframe、无需后端跳转,前端轮询 query.php 拿登录态:
<img src="https://um.yunjii.cn/php/api/qrcode.php?appid=1001&type=wx&redirect_uri=https://yourapp.com/callback&state=xxx&size=240×tamp=...&sign=...">
参数:
| 参数 | 必填 | 说明 |
|---|---|---|
appid | ✅ | 应用 ID |
type | ✅ | page / wx / alipay / qq / douyin / self |
redirect_uri | ✅ | 回调地址(域名需与后台一致) |
state | ✅ | 防 CSRF,随机字符串,原样返回 |
size | ⬜ | 二维码尺寸,默认 200,范围 100–600 |
timestamp | ✅ | 当前时间戳(秒) |
sign | ✅ | MD5 签名(见下方算法) |
响应:image/png(二维码图片)。扫码后用户在第三方平台授权,UM 携带 code 回调你的 redirect_uri。
兼容老方式:后端也可调 connect.php?act=login 拿到跳转 URL 再 302(见文末完整 Demo),但前端直接图片范式更轻、更快,推荐新接入使用。
用户在第三方平台(微信/支付宝等)完成扫码或授权。
这一步你不需要做任何事,UM 会自动处理。
用户授权后,UM 会带 code 参数跳转回你的 redirect_uri:
https://yourapp.com/callback?code=CODE_xxx&state=你传的state
你需要:
- 验证
state与第一步生成的是否一致(防 CSRF) - 取出
code,进入下一步
code 5 分钟内只能用一次,过期或重复消费返回 40163。
接口:GET https://um.yunjii.cn/php/connect.php?act=callback
参数:
| 参数 | 必填 | 说明 |
|---|---|---|
appid | ✅ | 应用 ID |
code | ✅ | 上一步拿到的 code |
timestamp | ✅ | 时间戳 |
sign | ✅ | 签名 |
响应:
{
"code": 1,
"data": {
"openid": "oXabc123...",
"nickname": "张三",
"avatar": "https://thirdwx.qlogo.cn/...",
"social_uid": "um_a1b2c3d4e5f6",
"login_type": "wx",
"token": "um_token_xxx..."
}
}
字段说明:
| 字段 | 说明 |
|---|---|
openid | 应用内用户唯一 ID(同应用不变) |
social_uid | UMID,跨应用唯一(同一用户在不同应用 UMID 相同) |
token | 后续 API 调用凭证(7 天有效) |
nickname / avatar | 用户资料 |
后续业务请求中,用 token 验证用户身份:
接口:GET https://um.yunjii.cn/php/check_token.php
参数:token + appid
响应:
{
"code": 1,
"data": {
"user_id": 12345,
"openid": "um_a1b2c3...",
"scope": "app",
"expire_at": "2026-07-13 12:00:00"
}
}
code=1 表示 token 有效,可放行请求。
签名算法
不用 SDK 时需要手动计算签名,3 行逻辑:
// 1. 收集所有 GET 参数(除 sign 外),按 key 字典序排列
ksort($params);
// 2. 拼接成字符串,末尾加 appkey
$signStr = '';
foreach ($params as $k => $v) $signStr .= "$k=$v&";
$signStr .= "appkey=$appkey";
// 3. MD5
$sign = md5($signStr);
timestamp 必须在当前时间 ±5 分钟内,否则返回 errcode=105。
完整 PHP Demo(B · 后端跳转范式,老系统兼容)
下方为 B(后端跳转) 写法,便于不便改前端的老系统参考复用。 新项目推荐用上面的 A(直接图片):照「第 1 步」用
<img src="api/qrcode.php">出图 + 前端轮询query.php拿登录态即可,无需这套 302 跳转。
复制以下代码,填入你的 appid 和 appkey,保存为 login.php 即可运行:
<?php
// ====== 配置 ======
$appid = '你的_appid';
$appkey = '你的_appkey';
$redirect_uri = 'https://yourapp.com/login.php';
// ====== 签名函数 ======
function makeSign($params, $appkey) {
ksort($params);
$str = '';
foreach ($params as $k => $v) $str .= "$k=$v&";
$str .= "appkey=$appkey";
return md5($str);
}
// ====== 主逻辑 ======
$act = $_GET['act'] ?? 'login';
if ($act === 'login') {
// 第一步:构造登录链接
$params = [
'act' => 'login',
'appid' => $appid,
'type' => 'wx', // 改成你要的平台
'redirect_uri' => $redirect_uri,
'state' => bin2hex(random_bytes(16)),
'timestamp' => time(),
];
$params['sign'] = makeSign($params, $appkey);
$resp = json_decode(file_get_contents(
'https://um.yunjii.cn/php/connect.php?' . http_build_query($params)
), true);
if ($resp['code'] === 1) {
header('Location: ' . $resp['data']['url']);
exit;
}
die('登录链接生成失败: ' . $resp['msg']);
}
if ($act === 'callback') {
// 第四步:code 换取用户信息
$params = [
'act' => 'callback',
'appid' => $appid,
'code' => $_GET['code'],
'timestamp' => time(),
];
$params['sign'] = makeSign($params, $appkey);
$resp = json_decode(file_get_contents(
'https://um.yunjii.cn/php/connect.php?' . http_build_query($params)
), true);
if ($resp['code'] === 1) {
$user = $resp['data'];
echo "登录成功!<br>";
echo "昵称: {$user['nickname']}<br>";
echo "头像: <img src='{$user['avatar']}' width=64><br>";
echo "UMID: {$user['social_uid']}<br>";
echo "Token: {$user['token']}<br>";
// TODO: 在这里创建会话,跳回首页
} else {
die('换取用户信息失败: ' . $resp['msg']);
}
}
使用方式:
- 修改
$appid和$appkey - 在 UM 控制台配置回调域名为你的域名
- 浏览器访问
https://yourapp.com/login.php?act=login - 用户扫码授权后会自动回调
?act=callback&code=xxx
用 SDK(更简单)
如果你用 PHP / JS / Python / 小程序,装 SDK 后签名自动生成:
$um = new UM($appid, $appkey, $callback, 'https://um.yunjii.cn/php');
$url = $um->login('wx', $state); // 一步生成登录链接
$user = $um->callback($_GET['code']); // 一步换取用户信息
详见 SDK 文档。
常见问题
| 问题 | 原因 | 解决 |
|---|---|---|
errcode=102 | appid 不存在或应用未审核 | 检查 appid,确认应用状态为"运行中" |
errcode=103 | 回调域名未授权 | 在控制台添加你的回调域名 |
errcode=105 | timestamp 过期 | 保证服务器时间正确,5 分钟内有效 |
errcode=106 | 签名验证失败 | 检查 appkey、参数排序、拼接格式 |
errcode=40163 | code 重复消费 | code 只能用一次,5 分钟过期 |