Creating a Stripe Customer Through a Cloud Function - android

I'm trying to register a customer through Firebase Realtime-Database, but I'm needing help adding a stripeID to the customer reference through a Cloud Function. I can register a customer just fine, but how can I append my Cloud Function when I click the sign up action because I'm not getting anything in the Firebase Function Logs right now? Thank you.
Cloud Function
exports.createStripeCustomer = functions.https.onCall( async (data, context) => {
const email = data.email
const uid = context.auth.uid
console.log(uid)
if (uid === null) {
console.log('Illegal access attempt due to unauthenticated attempt.')
throw new functions.https.HttpsError('internal', 'Illegal access attempt')
}
return stripe.customers
.create({ email: email })
.then((customer) => {
return customer["id"];
})
.then((customerId) => {
admin.database().ref("customers").child(uid).update({
stripeId: customerId,
email: email,
id: uid
})
})
.catch((err) => {
console.log(err);
throw new functions.https.HttpsError(
"internal",
" Unable to create Stripe user : " + err
);
});
})
WelcomeActivity.kt
signUpButton.setOnClickListener {
val registerStub = findViewById<ViewStub>(R.id.registerStub)
registerStub.inflate()
performRegister()
}
private fun performRegister() {
// MARK: - Register ViewStub Properties
val registerViewStubProfileImageButton = findViewById<ImageButton>(R.id.addPhotoImageButton)
val registerViewStubFullnameTextView = findViewById<TextInputEditText>(R.id.fullnameInputTextView)
val registerViewStubUsernameTextView = findViewById<TextInputEditText>(R.id.usernameTextInputView)
val registerViewStubEmailTextView = findViewById<TextInputEditText>(R.id.emailInputTextView)
val registerViewStubPasswordTextView = findViewById<TextInputEditText>(R.id.passwordTextInputView)
val registerViewStubConfirmPasswordTextView = findViewById<TextInputEditText>(R.id.confirmPasswordTextInputView)
val registerViewStubCancelButton = findViewById<Button>(R.id.secondCancelButton)
val registerViewStubSignUpButton = findViewById<Button>(R.id.secondSignUpButton)
val fullnameText = TextUtils.isEmpty(registerViewStubFullnameTextView.text)
val usernameText = TextUtils.isEmpty(registerViewStubUsernameTextView.text)
val emailText = TextUtils.isEmpty(registerViewStubEmailTextView.text)
val passwordText = TextUtils.isEmpty(registerViewStubPasswordTextView.text)
val confirmPasswordText = TextUtils.isEmpty(registerViewStubConfirmPasswordTextView.text)
registerViewStubSignUpButton.setOnClickListener {
FirebaseAuth.getInstance().createUserWithEmailAndPassword(registerViewStubEmailTextView.text.toString(), registerViewStubPasswordTextView.text.toString())
.addOnCompleteListener {
if (!it.isSuccessful) return#addOnCompleteListener
// else if successful
uploadImageToFirebaseStorage()
}
.addOnFailureListener {
Toast.makeText(this, "Failed to create user: ${it.message}", Toast.LENGTH_SHORT).show()
}
}
}
private fun uploadImageToFirebaseStorage() {
if (selectedPhotoUri == null) return
val filename = UUID.randomUUID().toString()
val ref = FirebaseStorage.getInstance().getReference("/customer_profile_images/$filename")
ref.putFile(selectedPhotoUri!!)
.addOnSuccessListener {
ref.downloadUrl.addOnSuccessListener {
saveCustomerToFirebaseDatabase(it.toString())
}
}
}
private fun saveCustomerToFirebaseDatabase(profileImageUrl: String) {
val registerStub = findViewById<ViewStub>(R.id.registerStub)
val registerViewStubFullnameTextView = findViewById<TextInputEditText>(R.id.fullnameInputTextView)
val registerViewStubUsernameTextView = findViewById<TextInputEditText>(R.id.usernameTextInputView)
val registerViewStubEmailTextView = findViewById<TextInputEditText>(R.id.emailInputTextView)
val uid = FirebaseAuth.getInstance().uid ?: ""
val ref = FirebaseDatabase.getInstance().getReference("/customers/$uid")
val customer = Customer(uid, registerViewStubFullnameTextView.text.toString(), registerViewStubUsernameTextView.text.toString(),
registerViewStubEmailTextView.text.toString(), profileImageUrl)
ref.setValue(customer)
.addOnSuccessListener {
uploadStripeCustomer()
registerStub.alpha = 0f
finish()
}
}
private fun uploadStripeCustomer(): Task<String> {
val registerViewStubEmailTextView = findViewById<TextInputEditText>(R.id.emailInputTextView)
val data = hashMapOf(
"email" to registerViewStubEmailTextView
)
return functions
.getHttpsCallable("createStripeCustomer")
.call(data)
.continueWith { task ->
val result = task.result?.data as Map<*, *>
result["createStripeCustomer"] as String
}
}

Related

How to insert a node with a value, depending on whether it exists or not

I am making a user registration with Authentication, but in turn, I insert these registrations in a collection of Firebase Realtime Database.
The structure of the database is as follows:
viewmodel of my register screen:
class RegisterViewModel : ViewModel() {
var email = mutableStateOf("")
var userName = mutableStateOf("")
var password = mutableStateOf("")
var status = mutableStateOf("1")
val state = mutableStateOf(RegisterState())
val user = FirebaseAuth.getInstance().currentUser
val loginPresenter = AuthPresenter()
fun registrar(email: String, password: String) {
viewModelScope.launch {
state.value = state.value.copy(isLoading = true)
if (
Common.isValidString(email.trim()) &&
Common.isValidPassword(password.trim()) &&
Common.isValidName(userName.value.trim()) &&
Common.isValidStatus(status.value)
) {
loginPresenter.signUp(email.trim(), password).addOnSuccessListener {
try {
val empleado = Empleado(
it.user!!.uid,
userName.value.trim(),
it.user!!.email!!,
status.value,
)
loginPresenter.createUserInDb(empleado).addOnSuccessListener {
state.value = state.value.copy(isSuccess = true)
}.addOnFailureListener { exception ->
state.value = state.value.copy(isError = exception.message)
}
} catch (e: Exception) {
state.value = state.value.copy(isError = e.message)
}
}.addOnFailureListener {
state.value = state.value.copy(isLoading = false)
state.value = state.value.copy(isError = it.message)
}
} else {
state.value = state.value.copy(isLoading = false)
state.value = state.value.copy(isError = "Rellena bien los campos")
}
}
}
fun dismiss() {
state.value = state.value.copy(isError = null)
}
And here the calls:
override suspend fun signUp(email: String, password: String): Task<AuthResult> {
return mAuth.createUserWithEmailAndPassword(email, password)
}
override fun createUserInDb(user: Empleado): Task<Void> {
return usersRef.child(user.uid!!).setValue(user.toMap())
}
First of all, the collection is: "employees"
and the document fields are:
.uid
.userName
.e-mail
.status
What I want to do is the following;
If there is no document in the "employees" collection;
The status field of the document to be inserted takes a value of 38. But if a document already exists in the collection, it takes the value of 1

Firestore DocumentReference type to object

As you can see in the picture, the documents in the person collection refer to the statistics collection.
I can pull this data like this
PersonRepository
override fun getPersonsFromFirestore(): Flow<Response<List<Person>>> = callbackFlow {
val snapshotListener =
personsCollection.addSnapshotListener { snapshot, e ->
val response = if (snapshot != null) {
val personList = snapshot.toObjects(Person::class.java)
Response.Success(personList)
} else {
throw Error(e?.message ?: e.toString())
}
trySend(response).isSuccess
}
awaitClose {
snapshotListener.remove()
}
}
Model
data class Person(
val id: Int=0,
val name: String="",
val surname: String="",
val image_url: String="",
val biography: String="",
val team: String="",
val statistics: DocumentReference? = null,
var personStatistics: PersonStatistics? = null
)
How can I convert Document Reference to object here?
I tried this first
override fun getPersonsFromFirestore(): Flow<Response<List<Person>>> = callbackFlow {
val snapshotListener =
personsCollection.addSnapshotListener { snapshot, e ->
val response = if (snapshot != null) {
val personList = mutableStateListOf<Person>()
snapshot.onEach {
val person = it.toObject(Person::class.java)
person.statistics!!.get().addOnSuccessListener {
val personStatistics = it.toObject(PersonStatistics::class.java)
person.personStatistics = personStatistics
}
personList.add(person)
}
//val personList = snapshot.toObjects(Person::class.java)
Response.Success(personList)
} else {
throw Error(e?.message ?: e.toString())
}
trySend(response).isSuccess
}
awaitClose {
snapshotListener.remove()
}
}
but in this approach Person Statistics comes first as null. It is added later. How can I bring them all at once? Or is there another better way?
Okey, This is how I solved it,
override fun getPersonsFromFirestore(): Flow<Response<List<Person>>> = callbackFlow {
val snapshotListener =
personsCollection.addSnapshotListener { snapshot, e ->
val response = if (snapshot != null) {
val personList = mutableStateListOf<Person>()
snapshot.onEach {
val person = it.toObject(Person::class.java)
val statistics = it.data["statistics"] as DocumentReference
statistics.addSnapshotListener { value, error ->
if (value!=null){
person.personStatistics = value.toObject(PersonStatistics::class.java)
personList.add(person)
}else{
throw Error(error?.message ?: error.toString())
}
}
}
Response.Success(personList)
} else {
throw Error(e?.message ?: e.toString())
}
trySend(response).isSuccess
}
awaitClose {
snapshotListener.remove()
}
}

Any alternative to showing chat messages on android app

this is the chat functionality on my app but the messages aren't appearing on my app although it is getting updated in the firebase. when I hardcoded the values it is working. this is the conversation activity. I've used a chat fragment and adapter as well. But the messages are just not getting posted on the app. any alternative solutions or a solution for this would be nice.
private val firebaseDB = FirebaseFirestore.getInstance()
private val userId = FirebaseAuth.getInstance().currentUser?.uid
private val conversationAdapter = ConversationAdapter(arrayListOf(), userId)
private var chatId: String? = null
private var imageUrl: String? = null
private var otherUserId: String? = null
private var chatName: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_conversation)
chatId = intent.extras.getString(PARAM_CHAT_ID)
imageUrl = intent.extras.getString(PARAM_IMAGE_URL)
chatName = intent.extras.getString(chatName)
otherUserId = intent.extras.getString(PARAM_OTHER_USER_ID)
if (chatId.isNullOrEmpty() || userId.isNullOrEmpty()) {
Toast.makeText(this, "chat room error", Toast.LENGTH_LONG).show()
finish()
}
topNameTV.text = chatName
populateImage(this, imageUrl, topPhotoIV, R.drawable.default_user)
messagesRV.apply {
setHasFixedSize(false)
layoutManager = LinearLayoutManager(context)
adapter = conversationAdapter
}
firebaseDB.collection(DATA_CHATS)
.document(chatId!!)
.collection(DATA_CHAT_MESSAGES)
.orderBy(DATA_CHAT_MESSAGE_TIME)
.addSnapshotListener{ querySnapshot, firebaseFirestoreException ->
if(firebaseFirestoreException != null){
firebaseFirestoreException.printStackTrace()
return#addSnapshotListener
}else{
if (querySnapshot != null){
for(change in querySnapshot.documentChanges){
when(change.type){
DocumentChange.Type.ADDED -> {
val message = change.document.toObject(Convo::class.java)
if(message != null){
conversationAdapter.addMessage(message)
messagesRV.post {
messagesRV.smoothScrollToPosition(conversationAdapter.itemCount -1)
}
}
}
}
}
}
}
}
}
fun onSend(v: View) {
if (!messageET.text.isNullOrEmpty()){
val message = Convo(userId, messageET.text.toString(), System.currentTimeMillis())
firebaseDB.collection(DATA_CHATS).document(chatId!!)
.collection(DATA_CHAT_MESSAGES)
.document()
.set(message)
messageET.setText("",TextView.BufferType.EDITABLE)
}
}
companion object {
private val PARAM_CHAT_ID = "Chat id"
private val PARAM_IMAGE_URL = "Image url"
private val PARAM_OTHER_USER_ID = "Other user id"
private val PARAM_CHAT_NAME = "Chat name"
fun newIntent(context: Context?, chatId: String?, imageUrl: String?, otherUserId: String?
chatName: String?): Intent{
val intent = Intent(context,ConversationActivity::class.java)
intent.putExtra(PARAM_CHAT_ID,chatId)
intent.putExtra(PARAM_IMAGE_URL, imageUrl)
intent.putExtra(PARAM_OTHER_USER_ID, otherUserId)
intent.putExtra(PARAM_CHAT_NAME, chatName)
return intent
}
}
}

how can i insert CALLBACK code in my code

When I created JOIN Action and LOGIN Action on Android app,
Aa problem has occurred.
Working with MVP pattern in LOGIN Action.
But the results on the logins aren't exactly what I want.
I'll show you the code.
class LoginModel {
var TAG = "LoginModel"
private var ID: String
private var PW: String
var resultTxt: String = ""
var auth: FirebaseAuth = FirebaseAuth.getInstance()
constructor(ID: String, PW: String) {
this.ID = ID
this.PW = PW
}
fun login(ID: String, PW: String) : String{
this.ID = ID
this.PW = PW
auth.signInWithEmailAndPassword(ID, PW)
.addOnCompleteListener { task ->
//
if (task.isSuccessful) {
val user = auth.currentUser
resultTxt = "Login Success"
} else {
resultTxt = "Login Failed"
}
}
return resultTxt
// I'd like to process the results based on the return.
// But it doesn't return the way I want it.
// I know it's related to asynchronous processing.
// So where should I put the callback function, and how should I write
// it?
}
}
Add a callback to your login function which get invoked after resultTxt has been set. Something along the following lines should work,
class LoginModel {
var TAG = "LoginModel"
private var ID: String
private var PW: String
var resultTxt: String = ""
var auth: FirebaseAuth = FirebaseAuth.getInstance()
constructor(ID: String, PW: String) {
this.ID = ID
this.PW = PW
}
fun login(ID: String, PW: String, callback: (String)->Unit) {
this.ID = ID
this.PW = PW
auth.signInWithEmailAndPassword(ID, PW)
.addOnCompleteListener { task ->
//
if (task.isSuccessful) {
val user = auth.currentUser
resultTxt = "Login Success"
} else {
resultTxt = "Login Failed"
}
//The callback get's invoked with your expected result value.
callback.invoke(resultTxt)
}
//Don't return here
//return resultTxt
// I'd like to process the results based on the return.
// But it doesn't return the way I want it.
// I know it's related to asynchronous processing.
// So where should I put the callback function, and how should I write
// it?
}
}
You can then call the method using,
login(id,password) { result ->
//Do what you want with the result here
}
fun login(ID: String, PW: String, callback:(String) -> Unit) {
this.ID = ID
this.PW = PW
auth.signInWithEmailAndPassword(ID, PW)
.addOnCompleteListener { task ->
if (task.isSuccessful) {
val user = auth.currentUser
resultTxt = "Login Success"
} else {
resultTxt = "Login Failed"
}
callback.invoke(resultTxt)
}
}
try this as a callback, it will return the value of resultTxt after it has executed.
Then, when you call the login method:
login(ID,PW){ result ->
//here, result is the value of the callback
}
ALTERNATIVELY
You can return the result and user of the call in a callback, like this:
fun login(ID: String, PW: String, callback:(Boolean, User?) -> Unit) {
this.ID = ID
this.PW = PW
auth.signInWithEmailAndPassword(ID, PW)
.addOnCompleteListener { task ->
if (task.isSuccessful) {
callback.invoke(true, auth.currentUser)
} else {
callback.invoke(false, null)
}
}
}
Then you can use it like this :
Login(id, password){ result: Boolean, user: User? ->
if(result){
//the result is successful
user?.let{ authUser ->
//here, authUser is your user
}
} else{
//the result was not successful
}
}

Facebook info not showing

I'm trying to get the user info with this code but is not showing on the activity
The profile picture and the name are not creating a new user on the base
What am I missing?
Does anyone had coded this using Kotlin?
private fun handleFacebookAccessToken(token: AccessToken) {
Log.d(TAG, "handleFacebookAccessToken:" + token)
val credential = FacebookAuthProvider.getCredential(token.token)
App.currentAuth.signInWithCredential(credential)
.addOnCompleteListener(this) { Log.d(TAG, "signInWithCredential:success") }
.addOnSuccessListener(this) { authResult ->
if (authResult != null) {
val firebaseUser = authResult.user
if (App.database_table_users.child(firebaseUser.uid) == null) {
var facebookId = ""
firebaseUser.providerData
.filter { it.providerId == FacebookAuthProvider.PROVIDER_ID }
.forEach { facebookId = it.uid }
val photoUrl = "https://graph.facebook.com/$facebookId/picture?width=1024&height=1024"
App.database_table_users.child(firebaseUser.uid).setValue(
User(firebaseUser.uid,
firebaseUser.email.orEmpty(),
firebaseUser.displayName.orEmpty(),
photoUrl,
false
)
)
}
}
}
.addOnFailureListener(this) { ex ->
if (ex is FirebaseAuthUserCollisionException) {
LoginManager.getInstance().logOut()
val ad = AlertDialog.Builder(this#LoginActivity)
ad.setMessage(getString(R.string.auth_user_collision))
ad.setPositiveButton(getString(R.string.ok), null)
ad.show()
} else {
ex.printStackTrace()
}
}
}
You must use FirebaseAuth.getInstance() instead of App.currentAuth.
For example;
val mAuth = FirebaseAuth.getInstance()
val credential = FacebookAuthProvider.getCredential(token)
mAuth.signInWithCredential(credential)
.addOnCompleteListener(this) { task ->
if (task.isSuccessful) {
val user = mAuth.currentUser
} else {
task.exception?.printStackTrace()
}
}
Try This it's work for me
private fun loginWithFaceBook()
{
LoginManager.getInstance().registerCallback(callbackManager, facebookCallBack)
LoginManager.getInstance().logInWithReadPermissions(this, Arrays.asList("public_profile","email"))
}
private val facebookCallBack = object : FacebookCallback<LoginResult> {
override fun onSuccess(result: LoginResult?) {
val graphRequest = GraphRequest.newMeRequest(result?.accessToken) { _, response ->
val graphObject = response.jsonObject
val id = if(graphObject.has("id")) graphObject.getString("id") else null
val email = if(graphObject.has("email")) graphObject.getString("email") else null
val firstName = if(graphObject.has("first_name")) graphObject.getString("first_name") else null
val lastName = if(graphObject.has("last_name")) graphObject.getString("last_name") else null
val photoUrl = if(graphObject.has("picture")) {
val picture : JSONObject = graphObject.getJSONObject("picture")
if(picture.has("data") && picture.has("url") && picture.getString("url").isNotBlank()) {
picture.getString("url")
}
else
null
}
else
val bundle = Bundle()
bundle.putString("fields", "id,first_name,last_name,name,picture,email,gender,birthday,link")
graphRequest.parameters = bundle
graphRequest.executeAsync()
}
override fun onError(error: FacebookException) {
when{
error.message != null -> showSnackbar(error.message.toString())
}
}
override fun onCancel() {
}
}

Categories

Resources