Các lỗi kỹ thuật thường gặp trong quá trình phát triển Zalo Mini App
Bài viết này tổng hợp các lỗi kỹ thuật thường gặp nhất trong quá trình phát triển Zalo Mini App để các lập trình viên có thể tra cứu và xử lý chúng:
1. Network Error
Đây là lỗi thường gặp nhất do nhu cầu gọi API (thông qua axios
/fetch
) từ Mini App đến Server của doanh nghiệp là rất phổ biến. Các nguyên nhân có thể dẫn đến lỗi trên bao gồm:
- CORS (phổ biến nhất)
- Gọi API không có
https://
. - Domain API hết hạn SSL.
- Custom header không được phép do có Access-Control-Allow-Headers
- Lỗi mạng khác (do thiết bị/do server)
1.1. CORS
Dấu hiệu để nhận biết lỗi CORS là khi bạn có thể gọi API thành công bằng Postman/cURL/localhost nhưng lại thất bại trên Zalo Mini App.
Mặc dù hay gọi là lỗi, nhưng thật ra đây là một cơ chế bảo mật của các trình duyệt web.
Để fix lỗi CORS, Server cần phải trả về response có chứa header Access-Control-Allow-Origin
với giá trị là origin của Mini App, cụ th ể là:
- https://h5.zdn.vn
- zbrowser://h5.zdn.vn
Mình xin nhấn mạnh là lỗi này cần fix ở Server. Những thông tin như "lỗi báo ở Mini App thì cần phải fix ở phía Mini App", hoặc "CORS là một cơ chế riêng do Zalo Mini App tự áp dụng", là không chính xác.
Một số biến thể khác của CORS bao gồm:
Nội dung lỗi | Nguyên nhân | Cách xử lý |
---|---|---|
Response to preflight request doesn't pass access control check | Lỗi này xảy ra khi bạn đã thiết lập CORS cho request chính nhưng chưa thiết lập CORS cho request tiền tố (preflight request). | Để khắc phục lỗi này khá đơn giản, bạn chỉ cần trả header Access-Control-Allow-Origin theo logic tương tự cho method OPTIONS . Tài liệu này có thể giúp bạn hiểu rõ hơn về khái niệm của preflight request cũng như cách mà CORS hoạt động. |
Access-Control-Allow-Origin cannot contain more than one origin | Lỗi này xảy ra khi bạn thiết lập header Access-Control-Allow-Origin với nhiều giá trị cùng một lúc. | Code mẫu để thiết lập CORS hợp lý bạn có thể xem qua ở đây. |
Ví dụ cụ thể:
❌ Không hợp lệ: Không trả về header Access-Control-Allow-Origin
.
❌ Không hợp lệ: Chỉ trả về header Access-Control-Allow-Origin
cho method GET/POST/PUT/DELETE, nhưng không trả về cho method OPTIONS.
❌ Không hợp lệ: trả về nhiều origin cách nhau bởi dấu phẩy:
Access-Control-Allow-Origin: https://h5.zdn.vn,zbrowser://h5.zdn.vn,http://localhost:3000
✅ Hợp lệ: kiểm tra origin từ request và chỉ trả về một giá trị tương ứng:
Access-Control-Allow-Origin: https://h5.zdn.vn # Gọi từ https://
Access-Control-Allow-Origin: zbrowser://h5.zdn.vn # Gọi từ zbrowser://
Access-Control-Allow-Origin: http://localhost:3000 # Gọi từ localhost:3000
1.2. Gọi API không có domain, không có https://
hoặc domain hết hạn SSL
Mini App khi chạy trên Zalo sẽ được chạy trong một Secure Context, nên việc gọi các API như trên sẽ không thành công do cơ chế bảo mật.
❌ Không hợp lệ:
fetch("https://118.63.103.143:443");
fetch("http://my-server.com/api");
✅ Hợp lệ:
fetch("https://my-server.com/api");
2. Minified React error #<mã lỗi>
Khi bạn gặp những lỗi dạng này, điều đó có nghĩa là code React của bạn đang có vấn đề ở đâu đó (chẳng hạn như dùng hooks không đúng quy tắc, set lại state trong lúc render, hoặc render những component không hợp lệ,...). Lý do bạn nhìn thấy những lỗi như này là vì React đã lược bỏ hết những nội dung lỗi chi tiết và map chúng với các mã lỗi khi bạn build ứng dụng để giảm kích thước và tăng performance cho ứng dụng của bạn. Nên bây giờ bạn cần phải nhấn vào link bên trong mã lỗi (đoạn ở giữa "...visit <link> for the full message or...") để xem nội dung chi tiết của lỗi đó, từ đó tìm cách khắc phục tương ứng.
3. Hình ảnh không hiển thị
Việc đặt một file hình ảnh (chẳng hạn như coffee.jpg
) ở một folder nào đó bên trong source code (chẳng hạn như public
) rồi sử dụng nó trong thẻ img như thế này có thể sẽ hoạt động khi bạn đang phát triển ứng dụng trên localhost
, nhưng sẽ không hoạt động trên Zalo Mini App thật sự.
❌ Không hợp lệ:
<img src="/coffee.jpg" />
// hoặc
<img src="../public/coffee.jpg" />
Thay vào đó, bạn cần phải sử dụng syntax import để Vite chủ động tìm đến các hình ảnh này và đóng gói nó theo source code ứng dụng của bạn. Ví dụ,
✅ Hợp lệ:
import coffee from "./coffee.jpg";
<img src={coffee} />;
4. Gọi các API Server-Server từ Mini App
Một vài API được thiết kế để gọi từ phía Server của bạn sang Server của Zalo, cụ thể:
- Decode token ra số điện thoại/vị trí
- Gửi thông báo đến người dùng
- Tất cả các API trong nhóm OpenAPI
- Một số API trong nhóm CheckoutSDK (
getOrderStatus
,updateOrderStatus
)
Đặc điểm chung của các API này là cần phải truyền theo private key hoặc app secret. Nên việc gọi các API này từ Mini App là một lỗ hổng bảo mật lớn, cũng như sẽ không hoạt động trong một số trường hợp do các cơ chế như CORS hoặc chặn IP.
Cách duy nhất để fix các lỗi này là mang những logic gọi API ra khỏi Mini App và implement ở phía Server của bạn.
5. API được gọi thành công nhưng không có dữ liệu trong quá trình phát triển
Trong quá trình phát triển ứng dụng sử dụng Zalo Mini App Studio/Extension/CLI, trình duyệt hoặc simulator chỉ có thể giúp bạn xem giao diện của Mini App, chứ không giúp bạn tích hợp được các flow như getAccessToken
hoặc createOrder
, vì các flow này yêu cầu ứng dụng của bạn phải được chạy bên trong môi trường thật của Zalo Mini App (bên trong ứng dụng Zalo).
Chế độ Device có thể giúp Mini App đang chạy bên trong ứng dụng Zalo chạy code từ server hot reload đang chạy trên máy tính của bạn, từ đó bạn sẽ có thể gọi được các API này thành công và nhận được dữ liệu thật:
6. Lỗi trên bản Live nhưng không biết do đâu
Hiện tại có hai cách để xem nội dung lỗi chi tiết trên phiên bản Live của Mini App của bạn:
- Cách 1: Thêm param
zDebug=true
vào deeeplink của ứng dụng của bạn. Ví dụ:https://zalo.me/s/194839900003483517/?zDebug=true
, khi đó icon Debug sẽ hiển thị kể cả trên phiên bản Live, từ đó bạn có thể xem Console logs, Network requests, Element inspector và sử dụng nhiều tính năng gỡ lỗi khác:
- Cách 2: Kết nối thiết bị Android qua cáp USB và sử dụng Google Chrome để gỡ lỗi. Cách này có thể giúp bạn xem được mã lỗi một cách triệt để hơn, cũng như sử dụng được các công cụ debug nâng cao như Profiling, Breakpoints,...
7. Lỗi chỉ xảy ra với người dùng ngoài tập Developer/Admin
Nếu như ứng dụng của bạn có sử dụng các API như:
getPhoneNumber
getLocation
openMediaPicker
requestCameraPermission
keepScreen
- Nhóm API Native Storage
thì bạn cần phải xin Cấp quyền sử dụng các API này cho Mini App ID của bạn (ở Bước 1 trong lúc gửi xét duyệt phiên bản, hoặc mục Quản lý > Quản lý quyền). Việc không xin các quyền này sẽ gây ra lỗi khi người dùng ngoài tập Developer/Admin sử dụng Mini App của bạn. Riêng đối với người dùng là Developer/Admin của Mini App, để phục vụ cho việc tích hợp, tất cả những API trên đều có thể được sử dụng.
8. Trang này không tìm thấy hoặc không hợp lệ. Xin lỗi vì sự bất tiện này.
Lỗi này xảy ra khi bạn mở một phiên bản thử nghiệm (Development/Testing) của Mini App bằng một tài khoản Zalo không phải là Developer/Admin của ứng dụng.
Để khắc phục lỗi này, bạn chỉ cần:
- Đăng nhập lại bằng một tài khoản có trong tập Developer/Admin.
- Hoặc sử dụng phiên bản đang Live của Mini App.
9. Ứng dụng đang trong giai đoạn phát triển, vui lòng thử lại sau!
Lỗi này xảy ra khi bạn mở một phiên bản Live của Mini App đang trong giai đoạn phát triển (chưa có bản Live).
10. Không tìm thấy Mini App trên Zalo Mini App Store hoặc thanh tìm kiếm của Zalo
Việc các Mini App không hiển thị trên Zalo Mini App Store hoặc thanh tìm kiếm của Zalo là do phía vận hành chủ động tắt tìm kiếm đối với Mini App. Các sự kiện có thể dẫn đến một Mini App bị tắt tìm kiếm bao gồm:
-
Mini App hiển thị form đăng nhập truyền thống (username và password) yêu cầu người dùng phải đăng nhập với tài khoản có sẵn. Theo mục 6.4. Đăng nhập để sử dụng Mini App, các Mini App sử dụng luồng đăng nhập này phải (1) thuộc nhóm nội bộ (trường học, công ty, ...) và (2) cần được truy cập từ Deeplink/QR code/Shortcut đã ghim vào màn hình chính. Do phần lớn người dùng Zalo sẽ không có tài khoản để hoàn tất flow đăng nhập này, nên họ sẽ không thể sử dụng Mini App của bạn.
-
Mini App có vấn đề tại thời điểm xét duyệt và có đồng thuận với bên tích hợp sẽ cho lên phiên bản (vì mục đích nào đó) nhưng không cho người dùng tìm kiếm.
Nếu như Mini App của bạn có nhu cầu được mở tìm kiếm lại, bạn sẽ cần phải:
- Thay đổi flow đăng nhập hoặc khắc phục các vấn đề còn tồn động.
- Submit một phiên bản mới để đội ngũ kiểm duyệt xem xét. Trong nội dung mô tả lúc gửi xét duyệt, bạn vui lòng đề cập đến việc yêu cầu mở lại tìm kiếm và hiển thị công khai.
11. Không thể cut/copy/paste nội dung bên trong Extension
Vấn đề này có liên quan đến việc sử dụng iframe bên trong Extension của Visual Studio Code trên MacOS, và hiện tại chưa có hướng giải quyết triệt để. Hiện tại, để sao chép nội dung từ Extension, bạn vui lòng workaround như sau:
- Bôi đen phần nội dung cần sao chép.
- Truy cập menu Edit > Copy.
Tương tự cho các thao tác như Cut và Paste.
12. Cannot find module '@vitejs/plugin-react-refresh'
Lỗi này xảy ra khi bạn đã thay thế @vitejs/plugin-react-refresh
(plugin cũ) bằng @vitejs/plugin-react
(plugin mới) nhưng chưa cập nhật lại thiết lập của Vite.
Để sửa lỗi này, bạn chỉ cần cập nhật lại vite.config.js
hoặc vite.config.ts
:
// thay
import reactRefresh from "@vitejs/plugin-react-refresh";
...
plugins: [
reactRefresh(),
...
// bằng
import react from "@vitejs/plugin-react";
...
plugins: [
react(),
...
13. You have reached your 30-day deployment limit. Please try again later.
Mỗi Mini App có quota deploy 300 lần/tháng đối với phiên bản Development, và 60 lần/tháng với phiên bản Testing. Lỗi trên xảy ra khi bạn đã sử dụng hết quota này.
14. The file size is too large.
Mỗi phiên bản Mini App có size limit là 10MB cho cả app và 3MB cho mỗi file. Nếu như Mini App của bạn đã đạt giới hạn này, bạn có thể:
- Đối với các static resource như ảnh, video: upload lên server của bạn hoặc sử dụng CDN.
- Đối với các file scripts quá nặng: sử dụng kỹ thuật code splitting theo hướng dẫn tại đây.
15. Lỗi CI/CD
Một trong những lỗi thường gặp nhất khi tích hợp CI/CD theo Hướng dẫn setup CI/CD cho Mini App là:
Error: Permission denied. Please login again. (Tips: Run 'zmp login')
Để khắc phục lỗi này, bạn cần kiểm tra lại các thông số như:
ZALO_APP_SECRET
vàZALO_REFRESH_TOKEN
phải khớp vớiZALO_APP_ID
. Một lỗi phổ biến là khi bạn sở hữu nhiều Zalo App, sử dụng công cụ lấy Access token/Refresh token của Zalo for Developers mà không chọn đúng ứng dụng trước khi nhấn nút "Lấy Access Token", dẫn đếnZALO_REFRESH_TOKEN
thuộc về mộtZALO_APP_ID
khác.- Không nhầm lẫn
MINI_APP_ID
vớiZALO_APP_ID
. Đây là 2 ID hoàn toàn khác nhau (mặc dù có liên hệ trực tiếp với nhau). Việc sử dụngMINI_APP_ID
ở bước cầnZALO_APP_ID
sẽ gây ra lỗi như tr ên. ZMP_TOKEN
trong file .env bị ghi đè bởi biến môi trường (environment variable). Lỗi này ít phổ biến hơn nhưng nếu xảy ra thì rất khó để nhận biết. Vui lòng đảm bảo rằng bạn không thiết lập biến môi trường nào mang tênZMP_TOKEN
bên trong runner.
Bạn có thể trực tiếp chạy các lệnh như NEW_ACCESS_TOKEN=<TOKEN> npx zmp-developer-token deploy <MINI_APP_ID>
và npx zmp-developer-token login <ZALO_APP_ID> <ZALO_APP_SECRET> <ZALO_REFRESH_TOKEN>
ngay trên máy tính cá nhân để test chứ không nhất thiết phải test trên runner.
16. Lỗi ES2015
Nếu bạn gặp lỗi tương tự như:
Transforming async generator functions to the configured target environment ("es2015") is not supported yet
Transforming for-await loops to the configured target environment ("es2015") is not supported yet
thì nguyên nhân là do bạn đang sử dụng một thư viện mà trong thư viện đó có sử dụng những tính năng mới của JavaScript, cụ thể hơn là các tính năng không tương thích ngược với ES2015 (là phiên bản mà Zalo Mini App mặc định target để đóng gói ứng dụng). Để giải quyết vấn đề này, bạn có thể:
-
Nâng target bằng cách thêm thiết lập bên dưới vào
vite.config.js
hoặcvite.config.ts
. Tuy nhiên điều này cũng sẽ giảm bớt độ tương thích của Mini App của bạn đối với các thiết bị cũ. -
Thay thế bằng một thư viện khác có cùng mục đích. Chẳng hạn bạn có thể dùng
fetch
thay choaxios
, ZaUI Components thay chomui/material
,...
17. View/Download file PDF
Sử dụng react-pdf@5.x để view file PDF ngay trên Mini App. Hạn chế design các flow tải file.
Hiện tại bạn có thể sử dụng openWebview
để mở một link PDF. Tuy nhiên, do bản chất là một web app chạy trên webview của Zalo, và Zalo là một native app chạy trên Android/iOS. Mỗi platform có cơ chế xử lý mở file PDF khác nhau, và cơ chế này còn phụ thuộc vào header Content-Disposition
của link file PDF. Cụ thể hơn:
Link PDF | Android | iOS |
---|---|---|
Header Content-Disposition mang giá trị là inline hoặc không có header này | Tải file và hiện trang trắng trên webview | Xem trực tiếp trên webview |
Header Content-Disposition mang giá trị là attachment | Tải file và hiện trang trắng trên webview | Không tải file và hiện "Không tải được dữ liệu. Nhấn để tải lại trang" trên webview |
Do những bất cập về mặt kỹ thuật như trên, chúng tôi khuyến khích bạn hạn chế thiết kế các flow liên quan đến việc tải file PDF. Thay vào đó, bạn có thể sử dụng một thư viện JavaScript để hiển thị trực tiếp file nội dung của file PDF như một thành phần trên giao diện ứng dụng của bạn.
Các phiên bản mới của thư viện react-pdf
có vấn đề tương thích với một lượng lớn các thiết bị cũ. Để đảm bảo tính tương thích với tất cả các thiết bị hỗ trợ Mini App, chúng tôi khuyến khích bạn sử dụng phiên bản react-pdf@5.x
.
18. Import zmp-sdk từ Cocos Creator
Cocos Creator có cơ chế import các thư viện JavaScript khác với các Mini App thông thường. Nên nếu bạn đang phát triển một Mini Game trên Cocos Creator, và gặp vấn đề khi import zmp-sdk
vào dự án, bạn có thể thử:
-
Đổi cú pháp import và sử dụng
zmp-sdk
như sau:import "reflect-metadata";
import sdk, { SDKCreator } from "zmp-sdk";
(sdk["default"] as SDKCreator).getAccessToken(); -
Hoặc tải
zmp-sdk
từ CDN.
19. TailwindCSS không apply style mới khi sử dụng Chế độ Device
Lỗi này xảy ra khi sử dụng Device Mode (không bật Kết nối trưc tiếp) với dự án sử dụng Vite 2.6.x. Để khắc phục lỗi này, bạn chỉ cần nâng cấp Vite lên phiên bản mới hơn:
npm i vite@^2.9
Nếu như sử dụng Zalo Mini App Extension, bạn sẽ cần phải execute command Developer: Reload Window
để thay đổi có hiệu lực.
20. "adb is not recognized..." hoặc "command not found: adb" khi sử dụng Kết nối trực tiếp với Device Mode
Kết nối trực tiếp với Device Mode có thể giúp Device Mode chạy nhanh hơn đáng kể. Tuy nhiên máy tính của bạn cần đảm bảo đã cài đặt Cầu gỡ lỗi Android (adb). Lỗi trên xảy ra khi máy tính của bạn không có adb
, hoặc đã cài đặt adb
nhưng không thiết lập biến môi trường cho nó. Vui lòng tham khảo tài liệu thiết lập biến môi trường phù hợp với hệ điều hành của bạn, và đảm bảo rằng adb
có thể được khởi chạy trực tiếp từ terminal:
✅ Hợp lệ:
$ adb
Android Debug Bridge version 1.0.41
Version 35.0.1-11580240
...
21. Các lỗi khác
Trên đây là những lỗi kỹ thuật thường gặp nhất trong quá trình phát triển Zalo Mini App. Nếu như bạn không thể tìm thấy lỗi mà mình gặp phải trong danh sách này, hãy:
- Đảm bảo bạn đang sử dụng phiên bản mới nhất của ZMP SDK, ZaUI, CLI, Extension, và ứng dụng Zalo trên điện thoại. Đôi khi các lỗi phát sinh từ việc bạn đang sử dụng một phiên bản cũ, hoặc đã được khắc phục trên các phiên bản mới hơn.
- Tìm kiếm trên Zalo Mini App Community. Có thể lỗi mà bạn gặp phải đã được giải quyết trước đây:
- Tạo một câu hỏi mới. Supporter của Zalo Mini App sẽ giúp bạn tìm ra lỗi và giải quyết nó trong thời gian sớm nhất có thể.