TypeScript SDK 封装
小程序与后端的通信分为两路:ztmp RPC 网关(批量调用)和 hapi REST API。以下封装基于小程序通信模块整理。
ZtmpClient — ztmp RPC 网关
小程序所有 ztmp 调用都走 POST /api/gateway,body 是 RPC 数组,支持批量调用。
typescript
const ZTMP_BASE = 'https://ztmp.chintiot.com';
class ZtmpClient {
private token = '';
setToken(t: string) {
this.token = t;
}
async call(...calls: Array<[string, ...any[]]>): Promise<any[]> {
const headers: Record<string, string> = { 'Content-Type': 'application/json' };
if (this.token) headers['token'] = this.token;
const res = await fetch(`${ZTMP_BASE}/api/gateway`, {
method: 'POST',
headers,
credentials: 'include',
body: JSON.stringify(calls),
});
if (!res.ok) throw new Error(await res.text());
return res.json();
}
async callOne(method: string, ...args: any[]): Promise<any> {
return (await this.call([method, ...args]))[0];
}
}批量调用示例
typescript
const [loginResult, memberList] = await ztmp.call(
['account.login', { type: 'wxmp_phonenumber', code: 'xxx', wx_login_code: 'yyy' }],
['ztmp.project.member_list', { currentPage: 1, pageSize: 10 }]
);小程序原始实现
javascript
// 小程序通信模块
exports.execute = async function(...t) {
const url = 'https://ztmp.chintiot.com/api/gateway';
if (e._.isArray(t[0])) {
return (await request(url, t)).data; // 批量: [[method, ...args], ...]
}
return (await request(url, [t])).data[0]; // 单个: [method, ...args] → 包装成数组
};HapiClient — hapi REST API
hapi 的接口是标准 REST,每个接口有独立路径。
typescript
const HAPI_BASE = 'https://hotel.chintiot.com';
class HapiClient {
constructor(private token: string = '') {}
async post(path: string, body: any): Promise<any> {
const headers: Record<string, string> = { 'Content-Type': 'application/json' };
if (this.token) headers['Authorization'] = `Bearer ${this.token}`;
const res = await fetch(`${HAPI_BASE}${path}`, {
method: 'POST',
headers,
body: JSON.stringify(body),
});
return res.json();
}
async get(path: string): Promise<any> {
const headers: Record<string, string> = {};
if (this.token) headers['Authorization'] = `Bearer ${this.token}`;
const res = await fetch(`${HAPI_BASE}${path}`, { headers });
return res.json();
}
}调用示例
typescript
await hapi.post('/client/room/control', {
ci: { room_id: 123 },
action: 'turn_on',
mac: '001122334455',
payload: { index: 0 }
});
const status = await hapi.post('/client/room/status', {
ci: { room_id: 123 }
});导出
typescript
export const ztmp = new ZtmpClient();
export const hapi = new HapiClient();错误处理
ztmp 错误
ztmp 区分业务错误和服务器错误,通过 HTTP 状态码区分:
业务错误(HTTP 4xx)——不应重试,应引导用户:
json
HTTP 401
{ "code": "USER_AUTH_FAILED", "message": "请登录" }服务器错误(HTTP 500)——可重试:
json
HTTP 500
{ "code": "SERVER_ERROR", "message": "..." }小程序通信模块会自动解析响应体,Error.message 为中文错误描述,Error.code 为错误键名,Error.statusCode 为 HTTP 状态码:
javascript
try {
await execute('account.login', { type: 'wxmp_login', code: 'xxx' });
} catch (e) {
console.log(e.code); // "USER_NOT_FOUND"
console.log(e.message); // "找不到会员"
console.log(e.statusCode); // 404
}完整错误码列表参见 错误码。
hapi 错误
hapi 所有响应均返回 HTTP 200,通过 code 字段区分成功/失败:
json
{ "code": 0, "message": "成功", "data": ... } // 成功
{ "code": 21001, "message": "手机号码或密码错误" } // 失败HTTP 状态码对照(ztmp)
| 状态码 | 含义 |
|---|---|
| 200 | 成功 |
| 400 | 参数错误 / 业务规则拒绝 |
| 401 | 未登录 / Token 过期 / 密码错误 |
| 403 | 无权操作 |
| 404 | 资源不存在 |
| 409 | 冲突(已被绑定 / 编号重复) |
| 500 | 服务器内部错误 |
