I'm trying to add a login with social media on my website, but I got some errors because the case is returning first before my HTTP request (Firebase):
firebase.auth().signInWithPopup
How can I use the async function in some way to the case await until the request is complete?
Here is the code:
login(provider, info) {
switch (provider) {
case this.EMAIL:
return firebaseAuth().signInWithEmailAndPassword(
info.email,
info.password
);
break;
case this.EMAILREGISTER:
break;
case this.GOOGLE:
var providerr = new firebase.auth.GoogleAuthProvider();
firebase.auth().signInWithPopup(providerr).then(function(result) {
// This gives you a Facebook Access Token. You can use it to access the Facebook API.
var token = result.credential.accessToken;
// The signed-in user info.
var user = result.user;
console.log(result);
// ...
}).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// The email of the user's account used.
var email = error.email;
// The firebase.auth.AuthCredential type that was used.
var credential = error.credential;
console.log(error);
// ...
});
//Right here I need to return the token and user async
break;
}
}
//here is the function who is calling:
handleLogin = () => {
const { email, password } = this.state;
if (!(email && password)) {
notification('error', 'Favor informar o email e senha');
return;
}
this.setState({
confirmLoading: true
});
const self = this;
let isError = false;
Firebase.login(Firebase.Google, '')
.catch(result => {
const message =
......
});
}
You can try using async/await so that it will wait till the data is returned. Something like this, just to get you started:
async login(provider, info) {
try {
switch (provider) {
case this.EMAIL:
return firebaseAuth().signInWithEmailAndPassword(
info.email,
info.password
);
break;
case this.EMAILREGISTER:
break;
case this.GOOGLE:
var providerr = new firebase.auth.GoogleAuthProvider();
// This gives you a Facebook Access Token. You can use it to access the Facebook API.
var result = await firebase.auth().signInWithPopup(providerr);
var token = result.credential.accessToken;
// The signed-in user info.
var user = result.user;
console.log(result);
// ...
break;
}
}
catch(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// The email of the user's account used.
var email = error.email;
// The firebase.auth.AuthCredential type that was used.
var credential = error.credential;
console.log(error);
// ...
}
}
}
Related
I found a tutorial on how to save the user's data under the uid in firestore. My function successfully retrieves the data and authenticates it, but it skips the firestore save function and jumps to the next window. I have two questions, why is it skipping the store in firebase function and why isn't reading the newly authenticated user as the current user when I set it and go to the next window? Sorry for all the similar questions, I'm trying different ways to do this and none have worked for me so far. I have provided my code below.
JS:
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
// Initialize variables
const auth = firebase.auth();
const db = firebase.firestore().collection("/studiopick/studios/users");
const element = document.querySelector("form");
element.addEventListener("submit", (event) => {
event.preventDefault();
// renamed from newStudio
// don't use alert - it blocks the thread
console.log("debug: retrieving data... please wait");
// Get data
(studioName = document.getElementById("studioName").value),
(email = document.getElementById("email").value),
(password = document.getElementById("password").value),
(firstName = document.getElementById("firstName").value),
(lastName = document.getElementById("lastName").value),
(phoneNumber = document.getElementById("phoneNumber").value);
console.log({ studioName, firstName, email }); // note added braces here
// Validate input fields
if (!validate_email(email) || !validate_password(password)) {
// TODO: replace this alert with updating the form with an error message
alert("Error with email or password");
return false; // cancel submission
}
if (
!validate_field(firstName) ||
!validate_field(lastName) ||
!validate_field(phoneNumber) ||
!validate_field(studioName)
) {
// TODO: replace this alert with updating the form with an error message
alert("One or More Extra Fields is Outta Line!!");
return false; // cancel submission
}
console.log("Info grab successful");
// creates the user, and waits for it to finish being created
firebase
.auth()
.createUserWithEmailAndPassword(email, password)
.then(function (userCredential) {
usersRef.doc(`${userCredential.user.uid}`).set({
studioName: studioName,
firstName: firstName,
lastName: lastName,
email: email,
phoneNumber: phoneNumber,
uid: userCredential.user.uid,
});
})
.catch(function (error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// [START_EXCLUDE]
if (errorCode == "auth/weak-password") {
alert("The password is too weak.");
} else {
alert(errorMessage);
}
console.log(error);
// [END_EXCLUDE]
});
const uid = firebase.auth().currentUser;
// once the above tasks succeed, navigate to the dashboard.
window.location.href = "studiodash.html?id=" + uid;
return false;
});
// Validate Functions
function validate_email(email) {
expression = /^[^#]+#\w+(\.\w+)+\w$/;
if (expression.test(email) == true) {
// Email is good
return true;
} else {
// Email is not good
return false;
}
}
function validate_password(password) {
// Firebase only accepts lengths greater than 6
if (password < 6) {
return false;
} else {
return true;
}
}
function validate_field(field) {
if (field == null) {
return false;
}
if (field.length <= 0) {
return false;
} else {
return true;
}
}
Ended up figuring it out myself. Hope this helps someone:
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
console.log("firebase ===", firebase);
// Initialize variables
const auth = firebase.auth();
const db = firebase.firestore().collection("/studiopick/studios/users");
const element = document.querySelector("form");
element.addEventListener("submit", (event) => {
event.preventDefault();
// renamed from newStudio
// don't use alert - it blocks the thread
console.log("debug: retrieving data... please wait");
// Get data
(studioName = document.getElementById("studioName").value),
(email = document.getElementById("email").value),
(password = document.getElementById("password").value),
(firstName = document.getElementById("firstName").value),
(lastName = document.getElementById("lastName").value),
(phoneNumber = document.getElementById("phoneNumber").value);
console.log({ studioName, firstName, email }); // note added braces here
// Validate input fields
if (!validate_email(email) || !validate_password(password)) {
// TODO: replace this alert with updating the form with an error message
alert("Error with email or password");
return false; // cancel submission
}
if (
!validate_field(firstName) ||
!validate_field(lastName) ||
!validate_field(phoneNumber) ||
!validate_field(studioName)
) {
// TODO: replace this alert with updating the form with an error message
alert("One or More Extra Fields is Outta Line!!");
return false; // cancel submission
}
console.log("Info grab successful");
// creates the user, and waits for it to finish being created
firebase
.auth()
.createUserWithEmailAndPassword(email, password)
.then(async (userCredential) => {
console.log("userCredential ===", userCredential);
var usersRef = db;
await usersRef.doc(`${userCredential.user.uid}`).set({
studioName: studioName,
firstName: firstName,
lastName: lastName,
email: email,
phoneNumber: phoneNumber,
uid: userCredential.user.uid,
});
console.log("firebase.auth().currentUser ===", firebase.auth().currentUser.uid);
const uid = firebase.auth().currentUser.uid;
// once the above tasks succeed, navigate to the dashboard.
window.location.href = "studiodash.html?id=" + uid;
})
.catch((error) => {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// [START_EXCLUDE]
if (errorCode == "auth/weak-password") {
alert("The password is too weak.");
} else {
alert(errorMessage);
}
console.log(error);
// [END_EXCLUDE]
});
return false;
});
// Validate Functions
function validate_email(email) {
expression = /^[^#]+#\w+(\.\w+)+\w$/;
if (expression.test(email) == true) {
// Email is good
return true;
} else {
// Email is not good
return false;
}
}
function validate_password(password) {
// Firebase only accepts lengths greater than 6
if (password < 6) {
return false;
} else {
return true;
}
}
function validate_field(field) {
if (field == null) {
return false;
}
if (field.length <= 0) {
return false;
} else {
return true;
}
}
I am trying to implement Stripe payment gateway in my Spring Boot project. I am facing problem from client side. I am trying to display any error or success message after a transaction. When I check my Stripe dashboard, then there is showing me successful transaction but from my JavaScript code, control is going to error block and displaying unexpected error. So I am not understanding where I am doing wrong and how to create token to send it to server side.
Below is JavaScript Code:
const stripe = Stripe(Public key);
let elements;
let clientsecret;
let paymentElement;
initialize();
checkStatus();
document.querySelector("#payment-form").addEventListener("submit", handleSubmit);
async function initialize(){
var url = "api/create-payment-intent";
$.post(url,{
}, function(data, status) {
if (data.status == "OK") {
if (data.statusCode == 1){
clientsecret = data.response.clientSecret;
const appearance = { theme: 'stripe',};
elements = stripe.elements({ appearance, clientsecret });
paymentElement = elements.create('card');
paymentElement.mount("#payment-element");
} else {
var error = data.responseMessage;
swal(error, "", "error");
}
}else {
var error = data.response;
}
});
}
async function handleSubmit(e) {
e.preventDefault();
setLoading(true);
const { error } = await stripe.confirmCardPayment(clientsecret,{
payment_method: {
card: paymentElement,
},
});
if (error) {
showMessage(error.message);
} else {
showMessage("An unexpected error occured.");
}
setLoading(false);
}
//Fetches the payment intent status after payment submission
async function checkStatus() {
const clientSecret = new URLSearchParams(window.location.search).get(
"payment_intent_client_secret"
);
if (!clientSecret) {
return;
}
const { paymentIntent } = await stripe.retrievePaymentIntent(clientSecret);
switch (paymentIntent.status) {
case "succeeded":
showMessage("Payment succeeded!");
break;
case "processing":
showMessage("Your payment is processing.");
break;
case "requires_payment_method":
showMessage("Your payment was not successful, please try again.");
break;
default:
showMessage("Something went wrong.");
break;
}
}
function showMessage(messageText) {
debugger
const messageContainer = document.querySelector("#payment-message");
messageContainer.classList.remove("hidden");
messageContainer.textContent = messageText;
setTimeout(function () {
messageContainer.classList.add("hidden");
messageText.textContent = "";
}, 4000);
}
// Show a spinner on payment submission
function setLoading(isLoading) {
if (isLoading) {
// Disable the button and show a spinner
document.querySelector("#submit").disabled = true;
document.querySelector("#spinner").classList.remove("hidden");
document.querySelector("#button-text").classList.add("hidden");
} else {
document.querySelector("#submit").disabled = false;
document.querySelector("#spinner").classList.add("hidden");
document.querySelector("#button-text").classList.remove("hidden");
}
}
There's problem in how you handle the payment result
if (error) {
showMessage(error.message);
} else {
showMessage("An unexpected error occured.");
}
It seems like you also show An unexpected error occured. even the payment is succeeded (i.e. when error is undefined). You might want to change the logic here.
use addEventListner() to show success or if you want to show or delete after a while you can use addEventListener() in setTimeOut function
I am trying to update my firebase realtime database with user info when I am creating new user through firebase password authentication. And on successful sign in I am moving to another page. The problem is that my database is not getting updated in the above scenario however if stay in the login page and don't change to any other url; the database gets updated.
Here's my create user code
firebase
.auth()
.createUserWithEmailAndPassword(email, password)
.then((userCredential) => {
// Signed in
var user = userCredential.user;
if (user !== null) {
const db = firebase.database();
db.ref("/").set({
uid: user.uid,
});
}
// ...
})
.catch((error) => {
var errorCode = error.code;
var errorMessage = error.message;
console.log(errorCode, errorMessage);
// ..
});
And here's where I'm switching to another page,
firebase.auth().onAuthStateChanged((user) => {
if (user) {
// User is signed in, see docs for a list of available properties
// https://firebase.google.com/docs/reference/js/firebase.User
var uid = user.uid;
console.log(user);
//If I remove the below line, database is updated
window.location.href = "../html/home.html";
// ...
} else {
// User is signed out
// ...
console.log("not logged in");
}
});
This calls is asynchronous:
db.ref("/").set({
uid: user.uid,
});
That means that the code continues to run after the set() function returns, and asynchronously sends the data to the database. But when you change window.location, it interrupts this write operation. That's also why it works when you don't send the user to a new location: the write operation can then complete without interruption.
A quick simple fix is to flag when you're updating the database:
isCreatingUser = true; // 👈 Flag that we're creating a user
firebase
.auth()
.createUserWithEmailAndPassword(email, password)
.then((userCredential) => {
var user = userCredential.user;
if (user !== null) {
const db = firebase.database();
db.ref("/").set({
uid: user.uid,
}).then(() => {
isCreatingUser = false; // 👈 We're done
window.location.href = "../html/home.html"; // 👈 Navigate away
}).catch((e) => {
isCreatingUser = false; // 👈 We're done
throw e;
})
}
// ...
})
.catch((error) => {
var errorCode = error.code;
var errorMessage = error.message;
console.log(errorCode, errorMessage);
// ..
isCreatingUser = false; // 👈 We're done
});
And then:
firebase.auth().onAuthStateChanged((user) => {
if (user && !isCreatingUser) {
...
You'll probably need some more synchronization, but that's the gist of it.
It always gives me "first argument (email) must be a valid string" and it doesn't login
i don't know if the problem is in the js code but im pretty sure it's not in the html .
and another question .. do i need the " onAuthStateChanged " function?
<script>
var rightAccount = 0;
var email = $("#inputEmail").val();
var password = $("#inputPassword").val();
SignIn();
function SignIn(email,password) {
firebase.auth().signInWithEmailAndPassword(email, password)
.then((user) => {
authStateListener();
rightAccount = 1;
//Signed in
// ...
})
.catch((error) => {
var errorCode = error.code;
var errorMessage = error.message;
console.log(errorMessage);
alert(errorMessage);
});
};
function authStateListener() {
// [START auth_state_listener]
firebase.auth().onAuthStateChanged((user) => {
if (user) {
var uid = user.uid;
currentUser = user;
console.log(currentUser.email + " has logged in")
} else {
// ...
}
});
// [END auth_state_listener]
};
if (rightAccount == 1) {
setTimeout(function Redirect() {
window.location.replace("Website/homePage.php");
}, 2000)
}
</script>
You must pass email and password values to function. Otherwise it will be give error.
...
var email = $("#inputEmail").val();
var password = $("#inputPassword").val();
SignIn(email, password); // <-- Here pass them
...
After logging in, the page to which the user is redirected is refreshing repeatedly.
Here is the javascript code:
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
window.location="comingsoon.html";
var user = firebase.auth().currentUser;
} else {
// No user is signed in.
}
});
function login(){
var userEmail = document.getElementById("email_field").value;
var userPass = document.getElementById("password_field").value;
firebase.auth().signInWithEmailAndPassword(userEmail, userPass).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
window.alert("Error : " + errorMessage);
// ...
});
}
function logout(){
firebase.auth().signOut();
}
You have to unsubscribe from the event listening function onAuthStateChanged after you execute your code. To do this you can write :
const unsubscribeAfterAuth = firebase.auth().onAuthStateChanged(function (user) {
if (user) {
window.location="comingsoon.html";
var user = firebase.auth().currentUser;
} else {
// No user is signed in.
}
});
unsubscribeAfterAuth();
This way you won't get updates after the first onAuthStateChanged as your function won't be listening to the event after the first call.