开发登录 Mini App 尚未发布
从零做出一个 Mini App:用这个人的 Micromeet 账号登录,再从它自己的后端以这个人的身份调用 Micromeet。每个函数的说明见登录,打包见打包与签名,包的全部规则见包规范。
整体流程
从第一次构建到用户打开 Mini App,谁做什么:
Cowork 每次打开都验签名,页面每读一个文件都核对;文件被改过就关闭这个 Mini App。
用户点了你的登录按钮之后:
页面始终拿不到密码、token 和 client secret。下面的步骤逐个做出每一部分。
1. 请 Micromeet 登记这个 Mini App
不能自助登记。把这些发给 Micromeet:
| 内容 | 示例 |
|---|---|
| AppID:小写反向域名 | ai.example.app |
| 名称(英文;中文可选)和开发方 | Example · Example Ltd |
| 需要的 scope | profile:read |
| 登录用户所在的区(SG、HK、ID) | HK |
| 后端的地址 | https://api.example.com |
每个区给你一个 client secret,只显示一次:存进后端的密钥存储。每个后端地址还会给你一个验证文件(第 2 步)。
2. 证明后端域名是你的
把这个文件放在 https://api.example.com/micromeet-miniapp-<16 个字符>.txt,用 HTTPS 返回 200,不能跳转,并一直留着;Micromeet 取回它来验证域名。开发时,后端可以跑在 http://localhost:<端口> 或 http://127.0.0.1:<端口>,在 Micromeet 允许的区不用放文件。见打包与签名里的「服务器域名」。
3. 写页面
安装 @micromeet-ai/miniapp-sdk(见打包与签名里的「构建」),然后:
js
import { maestroSdk } from '@micromeet-ai/miniapp-sdk';
const BACKEND = 'https://api.example.com'; // 验证过的服务器域名
export async function signIn() {
const sdk = maestroSdk(); // 不在 Cowork 里时为 null
if (!sdk?.auth) return { error: 'open_in_cowork' };
const login = await sdk.auth.login({ scopes: ['profile:read'] });
if (!login.ok) return { error: login.error };
const response = await fetch(`${BACKEND}/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ code: login.code, region: login.region })
});
return response.json(); // { session, name }:之后的请求带上 session
}- 在用户点击时调用
auth.login():Cowork 只在用户正在看的标签页上弹出确认卡。 auth.status()说明包是否已签名、Cowork 是否有人登录,可以用来决定是否显示登录按钮。- 脚本都放在文件里:内联
<script>不会运行。
4. 写后端
一个最小的 Node.js 后端:
js
import { createServer } from 'node:http';
import { randomUUID } from 'node:crypto';
import { createMiniappAuthClient, MiniappAuthError } from '@micromeet-ai/miniapp-sdk/server';
const APP_ID = 'ai.example.app';
const PAGE = `miniapp://${APP_ID}`; // 页面的 origin
// 每个区一个 client,用那个区的 secret。
const clients = { HK: createMiniappAuthClient({ appId: APP_ID, clientSecret: process.env.MINIAPP_SECRET_HK }) };
const sessions = new Map(); // 实际存进你的数据库
const reply = (res, status, body) => {
res.writeHead(status, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': PAGE, Vary: 'Origin' });
res.end(JSON.stringify(body));
};
createServer((req, res) => {
if (req.method === 'OPTIONS') {
res.writeHead(204, { 'Access-Control-Allow-Origin': PAGE, 'Access-Control-Allow-Methods': 'POST', 'Access-Control-Allow-Headers': 'Content-Type, Authorization' });
return res.end();
}
if (req.method !== 'POST' || req.url !== '/login') return reply(res, 404, { error: 'not_found' });
let raw = '';
req.on('data', (part) => (raw += part));
req.on('end', async () => {
try {
const { code, region } = JSON.parse(raw);
const auth = clients[region];
if (!auth) return reply(res, 400, { error: 'region_not_supported' });
const tokens = await auth.exchangeCode({ code, region });
const session = randomUUID();
sessions.set(session, { ref: tokens.user.ref, region, refreshToken: tokens.refreshToken });
reply(res, 200, { session, name: tokens.user.name });
} catch (error) {
reply(res, 400, { error: error instanceof MiniappAuthError ? error.code : 'bad_request' });
}
});
}).listen(8787);- 回答
Access-Control-Allow-Origin: miniapp://<appId>:这是页面的 origin,没有这个响应头,请求在页面里就失败了,到不了你的代码。 - 用
user.ref当用户的键,存好 refresh token,之后要调用 Micromeet 时用refresh换新 token。 - 页面只拿到你自己的会话;Micromeet 的 token 留在后端。
- 部署在你验证过的服务器域名上,开发时跑在 localhost。其他语言的后端做同样的调用(见登录里的「HTTP 调用」)。
5. 打包、签名、安装
- 在 Vite 插件里写
domains: ['https://api.example.com'],然后vite build(见打包与签名)。 - 运行
micromeet-miniapp verify miniapp-package,再把包交给 Micromeet;Micromeet 在每个区登记并签名这个版本,交回签好的manifest.json,把它放回包里。 - 运行
micromeet-miniapp verify miniapp-package --signed,然后micromeet-miniapp zip miniapp-package。 - 在 Cowork 里让 Agent 安装这个 zip,打开 Mini App,点登录。
正式版 Cowork 只打开 Micromeet 正式环境签名的版本;没有不签名的开发模式。
6. 开发与测试
- 不需要登录的界面和逻辑:在浏览器里
vite dev。那里maestroSdk()是null,显示一句提示代替登录按钮。 - 只有页面的文件被签名:改后端不需要新版本。页面尽量简单,逻辑放在后端。
- 改了页面的任何文件或
domains,都要换新的version,重新登记、签名、安装。 - 端到端测试登录需要:签好名的版本,加上登录了已登记区账号的 Cowork。
- 开发用的版本可以只写 localhost 域名;发布的版本不要带 localhost:不允许 localhost 的区会因此拒绝登录(
no_server_domain)。
出错怎么办
| 在哪里 | 看到什么 | 原因和处理 |
|---|---|---|
| Cowork | 提示这个 Mini App 未经认证,打不开 | 包没有签名、由别的 Micromeet 环境签名,或签名后改过文件:安装签好名的 zip |
| 页面 | app_not_available | 用户所在的区没有登记这个 AppID,或已停用 |
| 页面 | version_not_available | 这个版本没有在那个区登记,或已停用 |
| 页面 | no_server_domain | 这个版本在那个区没有验证过的服务器域名,或验证文件不在了 |
| 页面 | scope_denied | 请求了 Micromeet 没有给这个 Mini App 的 scope |
| 页面 | fetch 报跨域(CORS)错误 | 后端没有回答 Access-Control-Allow-Origin: miniapp://<appId> |
| 后端 | invalid_client | 这个区的 secret 不对,或已被更换 |
| 后端 | invalid_grant | code 已经用过、超过 5 分钟,或不是这个 AppID 的 |