@retion-miniapp/sdk 0.4.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,11 @@
4
4
 
5
5
  ## Unreleased
6
6
 
7
+ ## 0.4.1 — 2026-09-30
8
+
9
+ ### Docs
10
+ - README rút gọn: chỉ còn API reference (từng hàm, field, token, lỗi).
11
+
7
12
  ## 0.4.0 — 2026-09-30
8
13
 
9
14
  ### Added
package/README.md CHANGED
@@ -1,237 +1,141 @@
1
1
  # @retion-miniapp/sdk
2
2
 
3
- Kết nối web mini app (Vue, React, ...) với app Retion.
4
-
5
- Mini app là web của bạn, được app tải về máy và mở full màn hình trong 1 conversation. SDK làm 3 việc:
6
-
7
- 1. Cho biết mini app đang mở ở **page nào, khách nào** → `getRouteParams()`
8
- 2. Đưa **token** để gọi API backend của bạn → `getAccessToken()`
9
- 3. **Đóng** mini app → `closeApp()`
10
-
11
- Cùng 1 source chạy được **cả trong app lẫn trên web** (trình duyệt / iframe cũ) — ngoài app, SDK đọc thông tin từ query URL như hiện tại.
12
-
13
- ---
14
-
15
- ## 1. Cài đặt
3
+ SDK cho web mini app chạy trong app Retion.
16
4
 
17
5
  ```bash
18
6
  npm i @retion-miniapp/sdk
19
- npm i -D @retion-miniapp/cli # build + deploy lên Retion
20
- npx retion-miniapp init --app-id <app_id> --name "<Tên mini app>"
21
7
  ```
22
8
 
23
- `app_id` lấy trên [Retion Mini App Console](https://retion-miniapp-platform.vercel.app/console) (trùng `app_id` của widget, vd `66515701a2be1c03411c5723`).
24
-
25
- ## 2. Cấu hình project
26
-
27
- Mini app chạy từ file trên máy (không phải từ domain của bạn), nên cần 3 chỉnh nhỏ:
28
-
29
- **a. Đường dẫn asset tương đối** — `vite.config.ts`:
30
-
31
9
  ```ts
32
- export default defineConfig({
33
- base: './',
34
- });
10
+ import { getRouteParams, getToken, closeApp } from '@retion-miniapp/sdk';
35
11
  ```
36
12
 
37
- **b. Router dạng hash** (nếu dùng vue-router):
13
+ ---
38
14
 
39
- ```ts
40
- createRouter({ history: createWebHashHistory(), routes });
41
- ```
15
+ ## `getRouteParams()`
42
16
 
43
- **c. API gọi bằng URL tuyệt đối** + backend cho phép CORS origin `null`:
17
+ Thông tin conversation đang mở mini app. Đồng bộ, gọi lúc nào cũng được.
44
18
 
45
19
  ```ts
46
- const API_URL = import.meta.env.VITE_API_URL; // https://api.merchant.vn — không dùng "/api"
20
+ const { org_id, page_id, client_id } = getRouteParams();
47
21
  ```
48
22
 
49
- ## 3. Bọc SDK vào 1 file
50
-
51
- Không gọi SDK rải rác trong component. Tạo 1 file làm cầu nối duy nhất — sau này đổi gì chỉ sửa 1 chỗ:
52
-
53
- ```ts
54
- // src/lib/miniapp.ts
55
- import axios from 'axios';
56
- import { getRouteParams, getAccessToken, closeApp, isInHost } from '@retion-miniapp/sdk';
57
-
58
- /** Page + khách của conversation đang mở. */
59
- export const conversation = getRouteParams();
60
-
61
- /** HTTP client gọi backend của bạn — tự gắn token của page hiện tại. */
62
- export const api = axios.create({ baseURL: import.meta.env.VITE_API_URL });
63
-
64
- api.interceptors.request.use(async (config) => {
65
- config.headers.Authorization = `Bearer ${await getAccessToken()}`;
66
- return config;
67
- });
68
-
69
- /** Đóng mini app. Chạy trên web thì quay lại trang trước. */
70
- export const close = () => (isInHost() ? closeApp() : history.back());
71
- ```
72
-
73
- > Dùng `fetch` thay axios: gọi `await getAccessToken()` rồi gắn vào header y hệt.
23
+ | Field | Kiểu | Ý nghĩa |
24
+ |---|---|---|
25
+ | `org_id` | `string` | Tổ chức đang dùng app |
26
+ | `page_id` | `string` | Page (kênh) của conversation |
27
+ | `client_id` | `string` | Khách hàng của conversation |
28
+ | `message_id` | `string?` | Tin nhắn mở mini app (nếu mở từ 1 tin cụ thể) |
29
+ | `comment_id` | `string?` | Bình luận mở mini app (nếu mở từ bình luận) |
30
+ | `locale` | `string` | Ngôn ngữ app: `vi`, `en`, `id`, `lo`, `km`, `th`, `tl`, `zh` |
31
+ | `is_page_admin` | `1 \| 0` | `1` nếu người dùng là admin của page |
74
32
 
75
- ## 4. Dùng trong component
33
+ Ngoài app (trình duyệt / iframe cũ): đọc từ query URL.
76
34
 
77
- ```vue
78
- <script setup lang="ts">
79
- import { ref, onMounted } from 'vue';
80
- import { api, conversation, close } from '@/lib/miniapp';
35
+ ---
81
36
 
82
- const orders = ref([]);
37
+ ## `getToken(type)`
83
38
 
84
- onMounted(async () => {
85
- const { data } = await api.get('/orders', { params: { client_id: conversation.client_id } });
86
- orders.value = data;
87
- });
88
- </script>
39
+ Lấy token để gọi API. Luôn trả token **của page đang mở**. Gọi mỗi lần cần, không lưu lại.
89
40
 
90
- <template>
91
- <header>
92
- <h1>Đơn hàng</h1>
93
- </header>
94
- <OrderList :orders="orders" />
95
- <button @click="close">Xong</button>
96
- </template>
41
+ ```ts
42
+ const token = await getToken('chatbox');
97
43
  ```
98
44
 
99
- Chừa khoảng **100px bên phải header** — app phủ nút `••• | ✕` ở góc trên phải.
45
+ | `type` | Token | Cần quyền |
46
+ |---|---|---|
47
+ | `'access'` | Token của mini app cho page hiện tại | Không |
48
+ | `'partner'` | Token đối tác của page | `partner_token` |
49
+ | `'chatbox'` | Token đăng nhập của người dùng app (toàn quyền như người dùng) | `chatbox_token` |
100
50
 
101
- ## 5. Chạy thử trên trình duyệt
51
+ Quyền do admin bật trên Console (app → *Quyền lấy token*). Chưa bật → lỗi `PERMISSION_DENIED`.
102
52
 
103
- Truyền thông tin qua query URL như iframe hiện tại:
53
+ Ngoài app: đọc `?access_token=` / `?partner_token=` / `?chatbox_token=` trên URL.
104
54
 
105
- ```
106
- http://localhost:5173/?page_id=100179064765476&client_id=8385907281421695&access_token=<token test>
107
- ```
55
+ > `getAccessToken()` = `getToken('access')`.
108
56
 
109
- `getRouteParams()` và `getAccessToken()` đọc từ URL này; `closeApp()` không chạy được ngoài app (hàm `close` ở trên sẽ `history.back()`).
57
+ ---
110
58
 
111
- ## 6. Deploy
59
+ ## `closeApp()`
112
60
 
113
- ```bash
114
- export RETION_MINIAPP_API=https://retion-miniapp-platform.vercel.app/api
115
- export RETION_MINIAPP_TOKEN=<deploy token của app — lấy trên Console>
61
+ Đóng mini app, quay về màn chat.
116
62
 
117
- npx retion-miniapp deploy --channel testing # tự tăng version → build → upload
63
+ ```ts
64
+ await closeApp();
118
65
  ```
119
66
 
120
- Lên Console → version vừa deploy → **→ production**. Người dùng nhận bản mới ở lần mở mini app kế tiếp (app tải nền, không cần cập nhật app).
67
+ Ngoài app → lỗi `NOT_IN_HOST`.
121
68
 
122
69
  ---
123
70
 
124
- ## API
71
+ ## `isInHost()`
125
72
 
126
- | Hàm | Trả về | Trong app | Ngoài app (web / iframe) |
127
- |---|---|---|---|
128
- | `getRouteParams()` | `RouteParams` | Thông tin app truyền vào | Đọc query URL |
129
- | `getAccessToken()` | `Promise<string>` | Token của page hiện tại (app tự refresh) | Đọc `?access_token=` — không có thì lỗi `NOT_IN_HOST` |
130
- | `getToken(type)` | `Promise<string>` | `'access'` \| `'partner'` \| `'chatbox'` — `partner` / `chatbox` cần quyền (xem dưới) | Đọc `?access_token=` / `?partner_token=` / `?chatbox_token=` |
131
- | `onContextChange(cb)` | `() => void` | Gọi `cb` khi chuyển page / conversation (không nạp lại trang) | Không bao giờ gọi |
132
- | `closeApp()` | `Promise<void>` | Đóng mini app | Lỗi `NOT_IN_HOST` |
133
- | `onAppPaused(cb)` / `onAppResumed(cb)` | `() => void` | Mini app bị đóng (chạy ngầm) / mở lại | Không bao giờ gọi |
134
- | `isInHost()` | `boolean` | `true` | `false` |
135
-
136
- `RouteParams`: `page_id`, `client_id`, `org_id`, `message_id`, `comment_id`, `locale`, `is_page_admin`.
137
-
138
- ### Lỗi
139
-
140
- Mọi lỗi là `MiniAppError` có `code`:
141
-
142
- | `code` | Khi nào |
143
- |---|---|
144
- | `NOT_IN_HOST` | Chạy ngoài app mà gọi hàm cần app |
145
- | `PERMISSION_DENIED` | Mini app chưa được cấp quyền lấy token đó |
146
- | `TIMEOUT` | App không phản hồi sau 15s |
147
- | `NOT_SUPPORTED` | Phiên bản app hiện tại chưa hỗ trợ |
148
- | `HOST_ERROR` | Lỗi khác phía app (vd page chưa có token) |
73
+ `true` nếu đang chạy trong app Retion, `false` nếu trên trình duyệt / iframe cũ.
149
74
 
150
75
  ```ts
151
- import { getAccessToken, MiniAppError, ErrorCode } from '@retion-miniapp/sdk';
152
-
153
- try {
154
- await getAccessToken();
155
- } catch (e) {
156
- if (e instanceof MiniAppError && e.code === ErrorCode.HOST_ERROR) showLoginAgain();
157
- }
76
+ if (isInHost()) await closeApp();
77
+ else history.back();
158
78
  ```
159
79
 
160
- ### Token khác ngoài `access_token`
80
+ ---
161
81
 
162
- | Token | Là gì | Cần quyền |
163
- |---|---|---|
164
- | `access` | Token của mini app cho page hiện tại | Không — luôn được |
165
- | `partner` | Token đối tác của page | `partner_token` |
166
- | `chatbox` | Token đăng nhập của người dùng app (**toàn quyền** như người dùng) | `chatbox_token` |
82
+ ## `onContextChange(callback)`
167
83
 
168
- Quyền do **admin bật trên Console** (app → *Quyền lấy token*) — không khai trong code được. Chưa bật → `getToken()` lỗi `PERMISSION_DENIED`, và token đó cũng **không có trên URL**.
84
+ Mini app được mở ở page / conversation khác **mà không nạp lại trang**. Gọi lại API ở đây.
169
85
 
170
86
  ```ts
171
- const partnerToken = await getToken('partner');
87
+ onContextChange((next, prev) => load());
172
88
  ```
173
89
 
174
- ## Chuyển page / conversation
90
+ | Tham số | Ý nghĩa |
91
+ |---|---|
92
+ | `next` | `RouteParams` mới (như `getRouteParams()`) |
93
+ | `prev` | `RouteParams` trước đó |
175
94
 
176
- 1 mini app = 1 phiên duy nhất (theo `app_id`), load 1 lần. Khi người dùng mở mini app ở page / conversation khác:
95
+ Chỉ xảy ra khi `miniapp.config.json` có `"context_update": true`. Mặc định (`false`) app tự nạp lại trang → không cần hàm này. Đổi tổ chức luôn nạp lại trang.
177
96
 
178
- **Mặc định — không cần làm gì.** App nạp lại trang (cùng WebView, không tạo mới) với thông tin mới; code đọc param lúc mở như bình thường.
97
+ Trả về hàm huỷ lắng nghe.
179
98
 
180
- **Muốn nhanh hơn — không nạp lại trang:** đặt `"context_update": true` trong `miniapp.config.json` và thêm 1 dòng:
99
+ ---
181
100
 
182
- ```ts
183
- onMounted(load); // đã có
184
- onContextChange(load); // đổi page / conversation → chạy lại load()
185
- ```
101
+ ## `onAppPaused(callback)` / `onAppResumed(callback)`
186
102
 
187
- Trong `load()` vẫn gọi `getRouteParams()` / `getToken()` — luôn trả thông tin + token của page mới. Bỏ kết quả của request cũ nếu người dùng đổi page khi nó chưa về:
103
+ Mini app bị đóng (vẫn chạy ngầm) / được mở lại.
188
104
 
189
105
  ```ts
190
- let controller: AbortController | undefined;
191
-
192
- const load = async () => {
193
- controller?.abort(); // huỷ request của page trước
194
- controller = new AbortController();
195
- const { page_id } = getRouteParams();
196
- const res = await fetch(`${API}/pages/${page_id}`, {
197
- headers: { Authorization: await getToken('access') },
198
- signal: controller.signal,
199
- });
200
- // ...
201
- };
106
+ onAppPaused(() => clearInterval(timer)); // dừng polling, video...
107
+ onAppResumed(() => load()); // làm mới dữ liệu
202
108
  ```
203
109
 
204
- > Đổi **tổ chức (org)** luôn nạp lại trang — kể cả khi `context_update: true` — để dữ liệu org cũ không còn trong bộ nhớ.
110
+ Trả về hàm huỷ lắng nghe.
205
111
 
206
- **Đóng / mở lại:** mini app đóng lại vẫn chạy ngầm để mở lại tức thì. Dừng việc chạy nền khi bị đóng:
112
+ ---
207
113
 
208
- ```ts
209
- onAppPaused(() => clearInterval(pollTimer));
210
- onAppResumed(() => load());
211
- ```
114
+ ## Lỗi
212
115
 
213
- ## Hỏi đáp
116
+ Mọi lỗi là `MiniAppError`, có `code` và `method`.
214
117
 
215
- **Web đang chạy (iframe / trình duyệt) có bị ảnh hưởng khi cài SDK?**
216
- Không. Ngoài app SDK không gọi mạng, không đụng DOM; `getRouteParams` / `getAccessToken` đọc query URL như trước.
118
+ ```ts
119
+ import { MiniAppError, ErrorCode } from '@retion-miniapp/sdk';
217
120
 
218
- **Token hết hạn?**
219
- Gọi `getAccessToken()` mỗi lần cần (interceptor ở mục 3 đã làm vậy) — app tự trả token còn hạn. Không lưu token vào localStorage.
121
+ try {
122
+ await getToken('chatbox');
123
+ } catch (e) {
124
+ if (e instanceof MiniAppError && e.code === ErrorCode.PERMISSION_DENIED) { /* chưa được cấp quyền */ }
125
+ }
126
+ ```
220
127
 
221
- **Có phải tải lại mỗi lần mở?**
222
- Code mini app nằm sẵn trên máy, chỉ tải khi có version mới. Đóng rồi mở lại trong lúc app còn chạy → hiện ngay.
128
+ | `code` | Khi nào |
129
+ |---|---|
130
+ | `NOT_IN_HOST` | Chạy ngoài app mà gọi hàm cần app |
131
+ | `PERMISSION_DENIED` | Chưa được cấp quyền lấy token đó |
132
+ | `TIMEOUT` | App không phản hồi sau 15s |
133
+ | `NOT_SUPPORTED` | Phiên bản app hiện tại chưa hỗ trợ |
134
+ | `HOST_ERROR` | Lỗi khác phía app (vd page chưa có token) |
223
135
 
224
136
  ---
225
137
 
226
- ## Phát triển SDK
227
-
228
- ```bash
229
- npm i
230
- npm run check # typecheck + lint + test + build + publint
231
- npm run release:minor # ghi CHANGELOG mục "## Unreleased" trước
232
- ```
233
-
234
- Giao thức với app: xem chú thích đầu [`src/bridge.ts`](./src/bridge.ts).
138
+ Deploy lên app: [`@retion-miniapp/cli`](https://www.npmjs.com/package/@retion-miniapp/cli).
235
139
 
236
140
  ## License
237
141
 
package/dist/index.cjs CHANGED
@@ -149,7 +149,7 @@ var on = (event, listener) => {
149
149
  };
150
150
 
151
151
  // src/version.ts
152
- var SDK_VERSION = "0.4.0" ;
152
+ var SDK_VERSION = "0.4.1" ;
153
153
 
154
154
  // src/apis/app.ts
155
155
  var closeApp = () => call("closeApp");
package/dist/index.js CHANGED
@@ -147,7 +147,7 @@ var on = (event, listener) => {
147
147
  };
148
148
 
149
149
  // src/version.ts
150
- var SDK_VERSION = "0.4.0" ;
150
+ var SDK_VERSION = "0.4.1" ;
151
151
 
152
152
  // src/apis/app.ts
153
153
  var closeApp = () => call("closeApp");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@retion-miniapp/sdk",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Retion Mini App SDK — kết nối web mini app với app Retion",
5
5
  "keywords": [
6
6
  "retion",