I have a website and I want to receive notifications through it,
I got the “FCM Token”
But when someone sends me a message, I don’t receive the message and I don’t know the reason for the problem,
Please help me solve it
firebaseInit.js:
import { initializeApp } from "firebase/app";
import { getMessaging, getToken, onMessage } from "firebase/messaging";
const firebaseConfig = {
apiKey: "AIzaSyCSVOuA-4DT-NGyFXZ5IG13Q7gLpFoMa6Q",
authDomain: "sookler-plus-a1ef1.firebaseapp.com",
projectId: "sookler-plus-a1ef1",
storageBucket: "sookler-plus-a1ef1.appspot.com",
messagingSenderId: "868289122853",
appId: "1:868289122853:web:803612b64dcb557e04e5cc",
measurementId: "G-53P05PKSY1"
};
const app = initializeApp(firebaseConfig);
const messaging = getMessaging(app);
export const onMessageListener = () => {
return new Promise((resolve, reject) => {
const unsubscribe = onMessage(
messaging,
(payload) => {
console.log("Message received. ", payload);
resolve(payload);
unsubscribe();
},
(error) => reject(error)
);
});
};
export { messaging, getToken, onMessage };
firebase-messaging-sw.js:
/* eslint-disable no-undef */
importScripts(
"https://www.gstatic.com/firebasejs/9.0.0/firebase-app-compat.js"
);
importScripts(
"https://www.gstatic.com/firebasejs/9.0.0/firebase-messaging-compat.js"
);
const firebaseConfig = {
apiKey: "AIzaSyCSVOuA-4DT-NGyFXZ5IG13Q7gLpFoMa6Q",
authDomain: "sookler-plus-a1ef1.firebaseapp.com",
projectId: "sookler-plus-a1ef1",
storageBucket: "sookler-plus-a1ef1.appspot.com",
messagingSenderId: "868289122853",
appId: "1:868289122853:web:803612b64dcb557e04e5cc",
measurementId: "G-53P05PKSY1",
};
firebase.initializeApp(firebaseConfig);
const messaging = firebase.messaging();
self.addEventListener("push", function (event) {
console.log('push:::', event)
const payload = event.data ? event.data.json() : {};
const notificationTitle = payload.notification?.title || "New notification";
const notificationOptions = {
body: payload.notification?.body || "",
icon: payload.notification?.icon || "/firebase-logo.png",
};
event.waitUntil(
self.registration.showNotification(notificationTitle, notificationOptions)
);
});
self.addEventListener("install", (event) => {
console.log("Service worker installing");
// Perform install steps, e.g., caching static assets
});
self.addEventListener("activate", (event) => {
console.log("Service worker activating");
// Perform activation steps, e.g., cleaning up old caches
});
messaging.onMessage((payload) => {
console.log("Message received. ", payload);
});
messaging.onBackgroundMessage((payload) => {
console.log("Received background message ", payload);
const notificationTitle = payload.notification?.title || "New notification";
const notificationOptions = {
body: payload.notification?.body || "",
icon: payload.notification?.icon || "/firebase-logo.png",
};
self.registration.showNotification(notificationTitle, notificationOptions);
});
SigninForm.tsx:
import { getToken, messaging, onMessage } from "../../../firebaseInit";
const SignInForm = ({
setIsForgotPasswordClick,
setPhoneNumber,
}: {
setIsForgotPasswordClick?: any;
setPhoneNumber?: any;
}) => {
//location
const location = useLocation();
const redirect = location.state?.from?.pathname || "/home";
//translation
const { t } = useTranslation();
//form
const [loginSchema] = useLoginValidation();
// LoginModel
const {
control,
handleSubmit,
formState: { errors },
} = useForm<any>({
defaultValues: {
phone: "",
password: "",
},
resolver: yupResolver(loginSchema),
});
const [isButtonDisabled, setIsButtonDisabled] = useState<boolean>(false);
//redux
const { message, isOk } = useAppSelector((state) => state.authentication);
const dispatch = useAppDispatch();
const [fcmToken, setFcmToken] = useState<any>();
const token: any =
localStorage.getItem("fcmToken");
console.log("fcccm:", token);
useEffect(() => {
const handleMessage = (payload: any) => {
console.log("Message received. ", payload);
const notificationTitle =
payload.notification?.title || "New notification";
const notificationOptions = {
body: payload.notification?.body || "",
icon: payload.notification?.icon || "",
};
if (Notification.permission === "granted") {
new Notification(notificationTitle, notificationOptions);
}
};
const unsubscribe = onMessage(messaging, handleMessage);
return () => {
// Clean up listener on unmount
unsubscribe();
};
}, []);
const navigate = useNavigate();
useEffect(() => {
if (message?.length > 0) {
console.log("isOK");
if (isOk) {
console.log("isOK");
dispatch(successModal(message));
if (token) {
dispatch(updateToken(token)).then(() => {
navigate(redirect);
});
} else {
console.error("FCM Token is not available.");
}
} else {
setIsButtonDisabled(false);
dispatch(errorModal(message));
}
dispatch(resetStateStatus());
}
}, [message, isOk, dispatch, redirect]);
const onSubmit: SubmitHandler<LoginModel> = async (data) => {
setIsButtonDisabled(true);
dispatch(login(data));
};
const handleForgotPassword = () => {
setIsForgotPasswordClick(true);
};
return (
<Box component="form" onSubmit={handleSubmit(onSubmit)} autoComplete="off">
<Stack direction="column" rowGap="8px" sx={{ width: "100%", mb: "32px" }}>
<Stack
direction="column"
rowGap="16px"
sx={{ width: "100%", marginBottom: "7rem" }}
>
<Stack direction="column" sx={{ width: "100%" }}>
<Controller
name="phone"
control={control}
render={({ field: { name, value, ref, onChange } }) => (
<GeneralField
error={errors.phone}
name={name}
inputRef={ref}
value={value}
onChange={(e: any) => {
onChange(e);
setPhoneNumber(e.target.value); // Update phone number state
}}
focused={false}
inputProps={{
maxLength: 10,
}}
placeholder={t("mobile-number")}
icon={MobileIcon}
/>
)}
/>
{errors.phone ? <ErrorText errorText={errors.phone.message} /> : ""}
</Stack>
<Stack direction="column" rowGap="16px" sx={{ width: "100%" }}>
<Stack direction="column" sx={{ width: "100%" }}>
<Controller
name="password"
control={control}
render={({ field: { name, value, ref, onChange } }) => (
<PasswordField
name={name}
onChange={onChange}
value={value}
inputRef={ref}
placeholder={t("password")}
focused={false}
error={errors.password}
/>
)}
/>
{errors.password ? (
<ErrorText errorText={errors.password.message} />
) : (
""
)}
</Stack>
<HelperText
secondaryColor="primary.fg2"
primaryText=""
secondaryText="forgot-password"
secondaryTextTransform="capitalize"
callback={handleForgotPassword}
/>
</Stack>
</Stack>
<Stack direction="row" sx={{ width: "100%" }} justifyContent="flex-end">
<SignButton
variant="contained"
type="submit"
disabled={isButtonDisabled}
>
{t("continue")}
</SignButton>
</Stack>
</Stack>
</Box>
);
};
export default SignInForm;
App.tsx:
import { getToken, messaging, onMessageListener } from "./firebaseInit";
function App() {
const content = useRoutes(routes);
const [title] = useHeadTitle();
useEffect(() => {
const requestPermission = async () => {
try {
const permission = await Notification.requestPermission();
if (permission === "granted") {
console.log("Notification permission granted.");
const token = await getToken(messaging, {
vapidKey:
"BG-qtMNhGMcses3C612MtjKQZ9cbonJMI6pbQ4ec47jxtAjaQHepQvL45cANy_18B3I1xRP5WEi7mMvbCc3EnW0",
});
console.log("FCM token App:", token);
if (token) {
console.log("FCM Token:", token);
localStorage.setItem("fcmToken", token);
// Save the token to your server or local storage if needed
}
} else {
console.log("Notification permission denied.");
}
} catch (error) {
console.error("Error getting FCM token:", error);
}
};
requestPermission();
onMessageListener()
.then((payload) => {
console.log("Message received.", payload);
const notificationTitle =
payload.notification?.title || "New notification";
const notificationOptions = {
body: payload.notification?.body || "",
icon: payload.notification?.icon || "",
};
if (Notification.permission === "granted") {
new Notification(notificationTitle, notificationOptions);
}
})
.catch((error) => {
console.error("Error handling message:", error);
});
}, []);
useEffect(() => {
const registerServiceWorker = async () => {
if ("serviceWorker" in navigator) {
try {
const registration = await navigator.serviceWorker.register(
"/firebase-messaging-sw.js",
{ scope: "/" }
);
if (registration.installing) {
console.log("Service worker installing");
} else if (registration.waiting) {
console.log("Service worker installed");
} else if (registration.active) {
console.log("Service worker active");
}
} catch (error) {
console.error(`Service Worker registration failed: ${error}`);
}
}
};
registerServiceWorker();
}, []);
return (
<StyledEngineProvider injectFirst>
<ThemeProvider theme={theme}>
<GlobalStyles />
<HelmetProvider>
<Helmet>
<title>{title}</title>
</Helmet>
<MainLayout>{content}</MainLayout>
</HelmetProvider>
</ThemeProvider>
</StyledEngineProvider>
);
}
export default App;
package.json:
{
"name": "sookler",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite --host",
"build": "tsc && vite build",
"preview": "vite preview"
},
"dependencies": {
"@date-io/date-fns": "^2.17.0",
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.0",
"@firebase/app": "^0.10.7",
"@firebase/messaging": "^0.12.10",
"@googlemaps/react-wrapper": "^1.1.35",
"@hookform/resolvers": "^3.3.1",
"@lottiefiles/react-lottie-player": "^3.5.4",
"@mui/icons-material": "^5.14.1",
"@mui/lab": "5.0.0-alpha.137",
"@mui/material": "^5.14.2",
"@mui/styled-engine-sc": "^5.12.0",
"@mui/styles": "^5.14.1",
"@mui/x-data-grid": "^6.10.2",
"@mui/x-date-pickers": "^6.10.2",
"@react-oauth/google": "^0.11.1",
"@reduxjs/toolkit": "^1.9.5",
"axios": "^1.4.0",
"compressorjs": "^1.2.1",
"date-fns": "^2.30.0",
"firebase": "^10.12.5",
"form-data": "^4.0.0",
"framer-motion": "^10.15.0",
"google-maps-react": "^2.0.6",
"i18next": "^23.4.1",
"leaflet": "^1.9.4",
"moment": "^2.30.1",
"mui-one-time-password-input": "^1.2.5",
"react": "^18.2.0",
"react-custom-scrollbars": "^4.2.1",
"react-dom": "^18.2.0",
"react-helmet": "^6.1.0",
"react-helmet-async": "^1.3.0",
"react-hook-form": "^7.45.2",
"react-i18next": "^13.0.3",
"react-leaflet": "^4.2.1",
"react-redux": "^8.1.2",
"react-responsive-carousel": "^3.2.23",
"react-router-dom": "^6.14.2",
"react-toastify": "^9.1.3",
"react-verification-code-input": "^1.2.9",
"styled-components": "^6.0.5",
"swiper": "^8.4.7",
"yup": "^1.2.0"
},
"devDependencies": {
"@types/leaflet": "^1.9.8",
"@types/react": "^18.2.15",
"@types/react-dom": "^18.2.7",
"@vitejs/plugin-react": "^4.0.3",
"typescript": "^5.0.2",
"vite": "^4.4.5"
}
}