JavaScript SDK
JavaScript/TypeScript SDK 集成指南,支持浏览器和 Node.js。
安装
npm install @yunjii/um-sdk
# 或
pnpm add @yunjii/um-sdk
浏览器端
初始化
import { UM } from '@yunjii/um-sdk';
const um = new UM({
appid: 'your_appid',
appkey: 'your_appkey',
callback: 'https://your-app.com/login/callback',
apiUrl: 'https://um.yunjii.cn/php',
});
浏览器端 appkey 会暴露在前端代码中。生产环境务必在 BFF 层(如 Next.js API Routes)调用需要签名的接口,前端只调无需签名的接口。
生成登录跳转
const state = crypto.randomUUID();
sessionStorage.setItem('oauth_state', state);
const loginUrl = um.login('wx', state);
window.location.href = loginUrl;
回调处理
const url = new URL(window.location.href);
const code = url.searchParams.get('code');
const state = url.searchParams.get('state');
if (state !== sessionStorage.getItem('oauth_state')) {
throw new Error('State mismatch');
}
// 推荐:通过 BFF 后端换取用户信息(避免 appkey 暴露)
const res = await fetch('/api/auth/callback', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ code }),
});
const user = await res.json();
Node.js / Next.js BFF
初始化
import { UM } from '@yunjii/um-sdk/server';
const um = new UM({
appid: process.env.UM_APPID!,
appkey: process.env.UM_APPKEY!,
callback: 'https://your-app.com/api/auth/callback',
apiUrl: 'https://um.yunjii.cn/php',
});
Next.js API Route 示例
// app/api/auth/callback/route.ts
import { NextResponse } from 'next/server';
import { UM } from '@yunjii/um-sdk/server';
import { cookies } from 'next/headers';
const um = new UM({ /* config */ });
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const code = searchParams.get('code')!;
const user = await um.callback(code);
// 设置 httpOnly cookie
cookies().set('um_token', user.token, {
httpOnly: true,
secure: true,
sameSite: 'lax',
maxAge: 60 * 60 * 24 * 7, // 7 天
});
return NextResponse.redirect(new URL('/dashboard', request.url));
}
Token 验证中间件
// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { UM } from '@yunjii/um-sdk/server';
const um = new UM({ /* config */ });
export async function middleware(request: NextRequest) {
const token = request.cookies.get('um_token')?.value;
if (!token) return NextResponse.redirect(new URL('/login', request.url));
const result = await um.checkToken(token);
if (result.code !== 1) {
return NextResponse.redirect(new URL('/login', request.url));
}
// 注入用户信息到请求头
const requestHeaders = new Headers(request.headers);
requestHeaders.set('x-user-id', String(result.data.user_id));
return NextResponse.next({ request: { headers: requestHeaders } });
}
错误处理
import { UMError } from '@yunjii/um-sdk';
try {
const user = await um.callback(code);
} catch (err) {
if (err instanceof UMError) {
console.error(err.errCode); // 40163
console.error(err.message); // code 已被消费
}
}