Commit d8cbd2b9 authored by ThinhNC's avatar ThinhNC

feat(auth): integrate Zalo token-based phone auth and clean up login button UI

parent e693bcf4
import { useState } from "react"; import { useState } from "react";
import { getAccessToken, getPhoneNumber } from "zmp-sdk"; import { getAccessToken, getPhoneNumber, getUserInfo, getUserID } from "zmp-sdk";
import { useNavigate, useSnackbar } from "zmp-ui"; import { useNavigate, useSnackbar } from "zmp-ui";
import { authService } from "@/services/auth.service"; import { authService } from "@/services/auth.service";
import { useAuthStore } from "@/stores/auth-store"; import { useAuthStore } from "@/stores/auth-store";
...@@ -27,13 +27,42 @@ export function useZaloLogin(): UseZaloLoginReturn { ...@@ -27,13 +27,42 @@ export function useZaloLogin(): UseZaloLoginReturn {
throw new Error(t("auth.zalo.tokenFailed")); throw new Error(t("auth.zalo.tokenFailed"));
} }
// 2. Lấy số điện thoại từ Zalo SDK // 2. Lấy ID và thông tin người dùng từ client SDK
// `number` là field deprecated nhưng trả về SĐT thực trên Mini App let zaloId: string | undefined;
// `token` là flow mới: cần gửi lên server Zalo để đổi lấy SĐT let name: string | undefined;
const phoneResult = await getPhoneNumber(); let avatar: string | undefined;
const phoneNumber = phoneResult.number;
if (!phoneNumber) { try {
const id = await getUserID();
if (id) zaloId = id;
} catch (idErr) {
console.warn("getUserID error:", idErr);
}
try {
const infoResult = await getUserInfo({ autoRequestPermission: true });
if (infoResult?.userInfo) {
if (infoResult.userInfo.id) zaloId = infoResult.userInfo.id;
name = infoResult.userInfo.name;
avatar = infoResult.userInfo.avatar;
}
} catch (infoErr) {
console.warn("getUserInfo error or dismissed:", infoErr);
}
// 3. Lấy số điện thoại từ Zalo SDK (lấy mã token bảo mật 2 phút để backend giải mã)
let phoneToken: string | undefined;
let phoneNumber: string | undefined;
try {
const phoneResult = await getPhoneNumber();
phoneToken = phoneResult.token;
phoneNumber = phoneResult.number;
} catch (phoneErr) {
console.warn("getPhoneNumber error:", phoneErr);
}
if (!phoneToken && !phoneNumber) {
openSnackbar({ openSnackbar({
type: "warning", type: "warning",
text: t("auth.zalo.phoneDenied"), text: t("auth.zalo.phoneDenied"),
...@@ -41,8 +70,15 @@ export function useZaloLogin(): UseZaloLoginReturn { ...@@ -41,8 +70,15 @@ export function useZaloLogin(): UseZaloLoginReturn {
return; return;
} }
// 3. Gửi lên backend để xác thực + đăng nhập/tạo tài khoản // 4. Gửi lên backend để xác thực + giải mã SĐT + đăng nhập/tạo tài khoản
const response = await authService.loginWithZalo({ accessToken, phoneNumber }); const response = await authService.loginWithZalo({
accessToken,
phoneToken,
phoneNumber,
zaloId,
name,
avatar,
});
if (response.success && response.data) { if (response.success && response.data) {
setAuth( setAuth(
......
...@@ -78,22 +78,7 @@ const LoginPage: React.FC = () => { ...@@ -78,22 +78,7 @@ const LoginPage: React.FC = () => {
<span>{t("auth.zalo.loggingIn")}</span> <span>{t("auth.zalo.loggingIn")}</span>
</> </>
) : ( ) : (
<> <span>{t("auth.zalo.loginButton")}</span>
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
aria-hidden="true"
>
<rect width="24" height="24" rx="6" fill="white" />
<text x="3" y="18" fontSize="14" fontWeight="bold" fill="#0068FF">
Z
</text>
</svg>
<span>{t("auth.zalo.loginButton")}</span>
</>
)} )}
</button> </button>
......
...@@ -74,7 +74,11 @@ export const authService = { ...@@ -74,7 +74,11 @@ export const authService = {
async loginWithZalo(data: { async loginWithZalo(data: {
accessToken: string; accessToken: string;
phoneNumber: string; phoneToken?: string;
phoneNumber?: string;
zaloId?: string;
name?: string;
avatar?: string;
}): Promise<ApiResponse<{ user: User; accessToken?: string; refreshToken?: string }>> { }): Promise<ApiResponse<{ user: User; accessToken?: string; refreshToken?: string }>> {
const response = await apiClient.post("/auth/zalo-login", data); const response = await apiClient.post("/auth/zalo-login", data);
return response.data; return response.data;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment