Tạo tính năng xác thực số điện thoại bằng Firebase

18
Dịch vụ dạy kèm gia sư lập trình
Bài này thuộc phần 3 của 8 phần trong series Học Firebase cơ bản

Chắc hẳn bạn đã gặp rất nhiều ứng dụng cần phải xác thực số điện thoại , kiểu như xác thực qua mã OTP như:  Zalo, Whatsapp, các ứng dụng ngân hàng, ví điện tử… Bạn có nghĩ rằng tính năng này rất cao siêu không? Cần phải có hệ thống hạ tầng mạng, hay phải liên kết với nhà mạng gì đó không?

Đấy là chuyện của ngày xưa thôi, bây giờ bạn đã có công cụ giúp bạn tạo tính năng xác thực hiện đại này chỉ bằng vài dòng code. Bí kíp đó chính là sử dụng Firebase. Bài viết này mình sẽ chia sẻ cách tạo tính năng xác thực số điện thoại bằng Firebase, rất đơn giản.

Nếu bạn chưa thực sự hiểu rõ Fisebase thì đọc bài cũ của mình về Firebase – dịch vụ tuyệt vời của google nhé!

Logic cơ bản của tính năng này là: Điền số điện thoại, nhận mã OTP và sử dụng mã OTP để xác thực.

Chúng ta cùng bắt đầu nhé

Xác thực số điện thoại bằng firebase

Khi nào thì ứng dụng cần phải xác thực số điện thoại người dùng?

Ứng dụng của bạn cần xác thực số điện thoại của người dùng khi:

  • Hạn chế người dùng ảo: Khi bạn xác thực số điện thoại, bạn sẽ hạn chế người dùng đăng kí nhiều tài khoản ảo. Mặc dù ở Việt Nam, tình trạng SIM rác vẫn còn rất phổ biến nhưng dù sao có tính năng này cũng hạn chế phần nào.
  • Cần tăng giá trị người dùng: Khi bạn đã các thực người dùng bằng số điện thoại thì việc đây là tài khoản thật sự, không phải tài khoản ảo. Điều này làm tăng giá trị cho mỗi tài khoản trên ứng dụng của bạn
  • Cần tăng tính bảo mật và trải nghiệm người dùng: Với người dùng đã xác thực, bạn có thể sử dụng số điện thoại người dùng như là một cổng an ninh, tăng cường tính bảo mật. Mình ví dụ như: Bạn có thể khôi phục mật khẩu thông qua số điện thoại, hay gửi mã OTP mỗi khi thực hiện thanh toán…

Tại sao lại lựa chọn Firebase?

Để có thể làm được tính năng xác thực số điện thoại, bạn cần phải sử dụng một dịch vụ SMS nào đó.

Nhưng với Firebase thì bạn được MIỄN PHÍ hoàn toàn, quá tuyệt phải không?

Với Free plan của Firebase, bạn sẽ có 10,000 tin nhắn mỗi tháng. Theo mình như vậy là đủ dùng cho một ứng dụng vừa và nhỏ.

Nếu bạn có nhu cầu dùng thêm thì có thể thanh toán. Bạn có thể tham khảo bảng giá tại đây

Chúng ta cùng nhau tìm hiểu các tích hợp tính năng xác thực này vào ứng dụng Android nhé

Tạo một dự án Android Studio mới

Bạn tạo một dự án mới bằng Android Studio như  bình thường

Nếu bạn chưa biết cách thực hiện thì có thể tham khảo bài viết: Hướng dẫn toàn tập về cách sử dụng Android Studio

#1. Thêm Firebase Authentication vào dự án

Trong Android Studio, bạn chọn tools -> firebase. Android Studio sẽ hiển thị màn hình để hướng dẫn bạn thêm firebase service vào dự án. Bạn cứ bình tĩnh làm theo hướng dẫn của nó là được

#2. Bật tính năng Firebase Phone Authentication

Phần này, bạn vào Firebase Console, mở dự án mà bạn muốn tích hợp tính năng xác thực.

Sau đó chọn Sign In Method -> Bật Phone Authentication

xác thực số điện thoại
Bật tính năng xác thực trên Firebase

#3. Thiết kế giao diện ứng dụng Android

Trước khi bắt tay vào thiết kế giao diện cho ứng dụng, mình muốn note lại là: Với tính năng Sign In, chúng ta sẽ cần 2 Activities.

Một Activity để người dùng nhập số điện thoại và một Activity để nhập mã xác thực được nhận qua SMS

Màn hình nhập số điện thoại

Màn hình này mình làm đơn giản thôi, chỉ có một Edittext để nhập số điện thoại và một Button

Các bạn có thể tham khảo đoạn mã bên dưới (màn hình này mình đặt tên file layout là activity_main.xml )

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
 
    <RelativeLayout
        android:id="@+id/relativeLayout"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:background="@color/colorPrimary"
        android:orientation="horizontal">
 
        <ImageView
            android:layout_width="120dp"
            android:layout_height="120dp"
            android:layout_centerHorizontal="true"
            android:layout_centerVertical="true"
            android:background="@drawable/ic_logo" />
 
    </RelativeLayout>
 
    <ImageView
        android:id="@+id/imageView"
        android:layout_width="match_parent"
        android:layout_height="120dp"
        android:layout_below="@id/relativeLayout"
        android:layout_marginTop="-50dp"
        android:background="@drawable/waves" />
 
    <RelativeLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/imageView"
        android:orientation="vertical"
        android:padding="20dp">
 
        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="25dp"
            android:text="May I ask your phone number?"
            android:textAppearance="@style/Base.TextAppearance.AppCompat.Headline"
            android:textColor="@color/colorPrimary" />
 
        <EditText
            android:id="@+id/editTextMobile"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/textView"
            android:layout_marginTop="20dp"
            android:digits="0123456789"
            android:drawableLeft="@drawable/ic_phone"
            android:drawablePadding="10dp"
            android:hint="enter your mobile number"
            android:inputType="phone"
            android:maxLength="10" />
 
        <Button
            android:id="@+id/buttonContinue"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/editTextMobile"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="15dp"
            android:background="@color/colorPrimaryDark"
            android:text="Continue"
            android:textAllCaps="false"
            android:textColor="#cdd8f1" />
 
    </RelativeLayout>
 
</RelativeLayout>

Màn hình nhập mã xác thực

Sau khi thiết kế xong màn hình nhập số điện thoại, giờ đến màn hình nhập mã xác thực. Màn hình này cũng giống màn hình trước, tức là cũng có một EditText để nhập code.

Tuy nhiên, có một điểm mới là ứng dụng sẽ tự động detect được SMS và điền mã code

Đầu tiên là bạn tạo một Activity có tên là VerifyPhoneActivity.

Sau đó tạo một một layout cho nó, mình đặt file layout có tên là activity_verify_phone.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".VerifyPhoneActivity">
 
    <RelativeLayout
        android:id="@+id/relativeLayout"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:background="@color/colorPrimary"
        android:orientation="horizontal">
 
        <ImageView
            android:layout_width="120dp"
            android:layout_height="120dp"
            android:layout_centerHorizontal="true"
            android:layout_centerVertical="true"
            android:background="@drawable/ic_logo" />
 
    </RelativeLayout>
 
    <ImageView
        android:id="@+id/imageView"
        android:layout_width="match_parent"
        android:layout_height="120dp"
        android:layout_below="@id/relativeLayout"
        android:layout_marginTop="-50dp"
        android:background="@drawable/waves" />
 
    <RelativeLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/imageView"
        android:orientation="vertical"
        android:padding="20dp">
 
        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="25dp"
            android:text="Wait for the code I sent You"
            android:textAppearance="@style/Base.TextAppearance.AppCompat.Headline"
            android:textColor="@color/colorPrimary" />
 
        <ProgressBar
            android:id="@+id/progressbar"
            android:layout_below="@id/textView"
            android:layout_centerHorizontal="true"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
 
        <EditText
            android:id="@+id/editTextCode"
            android:layout_width="200dp"
            android:layout_height="wrap_content"
            android:layout_below="@id/progressbar"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="10dp"
            android:digits="0123456789"
            android:drawablePadding="10dp"
            android:hint="enter verification code"
            android:inputType="phone"
            android:maxLength="10" />
 
        <Button
            android:id="@+id/buttonSignIn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/editTextCode"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="15dp"
            android:background="@color/colorPrimaryDark"
            android:text="Sign In"
            android:textAllCaps="false"
            android:textColor="#cdd8f1" />
 
    </RelativeLayout>
 
</RelativeLayout>

Ở bước này, mình chỉ mới tạo layout thôi, chứ chưa hề code cho logic ứng dụng nhé. Cứ bình tĩnh

Tạo màn hình Profile

Màn hình mình tạo ra với mục đính duy nhất là chính là thông báo cho người dùng biết đã xác thực số điện thoại thành công.

Như vậy là phần layout đã xong. Chúng ta bắt tay vào code logic cho tính năng xác thực

Lấy số điện thoại được nhập từ người dùng

Quay  trở lại MainActivity.java và viết đoạn code sau

findViewById(R.id.buttonContinue).setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {

        String mobile = editTextMobile.getText().toString().trim();

        if(mobile.isEmpty() || mobile.length() < 10){
            editTextMobile.setError("Enter a valid mobile");
            editTextMobile.requestFocus();
            return;
        }

        Intent intent = new Intent(MainActivity.this, VerifyPhoneActivity.class);
        intent.putExtra("mobile", mobile);
        startActivity(intent);
    }
});

Đoạn code trên chỉ đơn giản là lấy số điện thoại từ EditText và gửi nó qua VerifyPhoneActivity bằng Intent

Xác thực số điện thoại

#1. Gửi mã xác thực tới  điện thoại

Đây là đoạn mã sử dụng Firebase để gửi mã xác thực, đơn giản chỉ là một dòng code thôi

private void sendVerificationCode(String mobile) {
        PhoneAuthProvider.getInstance().verifyPhoneNumber(
                "+84" + mobile,
                60,
                TimeUnit.SECONDS,
                TaskExecutors.MAIN_THREAD,
                mCallbacks);
    }


    private PhoneAuthProvider.OnVerificationStateChangedCallbacks mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
        @Override
        public void onVerificationCompleted(PhoneAuthCredential phoneAuthCredential) {
            //Getting the code sent by SMS
            String code = phoneAuthCredential.getSmsCode();
            
            //sometime the code is not detected automatically
            //in this case the code will be null
            //so user has to manually enter the code 
            if (code != null) {
                editTextCode.setText(code);
                //verifying the code
                verifyVerificationCode(code);
            }
        }

        @Override
        public void onVerificationFailed(FirebaseException e) {
            Toast.makeText(VerifyPhoneActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
        }

        @Override
        public void onCodeSent(String s, PhoneAuthProvider.ForceResendingToken forceResendingToken) {
            super.onCodeSent(s, forceResendingToken);
            mVerificationId = s;
            mResendToken = forceResendingToken;
        }
    };

Mình sẽ giải thích tác dụng của từng hàm trong đoạn mã trên

sendVerificationCode(): Hàm này có tác dụng gửi mã xác thực. Bạn cần phải điền cả mã quốc gia, ví dụ trên là mã +84 cho Việt Nam. Nhưng thực tế, có thể ứng dụng của bạn hỗ trợ nhiều thị trường quốc gia khác nhau. Nên không nên hard code mã quốc gia, thay vì đó bạn nên thêm một mục lựa chọn quốc gia hoặc để người dùng nhập mã quốc gia.

mCallbacks: Đây là callback để bạn biết là mã code đã được gửi rồi hay chưa. Chúng ta có 3 hàm:

  • onCodeSent(): Hàm này được gọi khi mã code đã được gửi thành công.
  • onVerificationFailed(): Hàm này được gọi khi không gửi được mã code. Chúng ta cần thông báo cho người dùng biết. Ở ví dụ này mình đơn giản là hiển thị một Toast thông báo.
  • onVerificationCompleted(): Hàm này được gọi khi bạn xác thực thành công. Tức là mã code nhập vào đúng với mã đã gửi.

#2. Tiến hành xác thực và đăng nhập

Để xác thực, chúng ta sử dụng đoạn code sau. Nếu xác thực thành công thì cho người dùng Sign in vào ứng dụng.

private void verifyVerificationCode(String otp) {
    //creating the credential
    PhoneAuthCredential credential = PhoneAuthProvider.getCredential(mVerificationId, otp);
    //signing the user
    signInWithPhoneAuthCredential(credential);
}
private void signInWithPhoneAuthCredential(PhoneAuthCredential credential) {
    mAuth.signInWithCredential(credential)
            .addOnCompleteListener(VerifyPhoneActivity.this, new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    if (task.isSuccessful()) {
                        //verification successful we will start the profile activity
                        Intent intent = new Intent(VerifyPhoneActivity.this, ProfileActivity.class);
                        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
                        startActivity(intent);
                    } else {
                        //verification unsuccessful.. display an error message
                        String message = "Somthing is wrong, we will fix it soon...";
                        if (task.getException() instanceof FirebaseAuthInvalidCredentialsException) {
                            message = "Invalid code entered...";
                        }
                        Snackbar snackbar = Snackbar.make(findViewById(R.id.parent), message, Snackbar.LENGTH_LONG);
                        snackbar.setAction("Dismiss", new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                            }
                        });
                        snackbar.show();
                    }
                }
            });
}

Tất cả chỉ có vậy thôi

Tổng kết

Như vậy mình đã hoàn thành bài viết hướng dẫn xây dựng tính năng xác thực số điện thoại sử dụng Firebase. Nếu bạn vẫn còn khúc mắc thì có thể download toàn bộ source code của bài hướng dẫn tại đây.

Mình hi vọng bài viết sẽ giúp ích cho bạn. Nếu thấy hay thì đừng ngại chia sẻ bài viết cho bạn bè cùng đọc nhé

Xem tiếp các bài trong Series
Phần trước: Xây dựng Car Location Tracking cho Android với FirebasePhần kế tiếp: Xây dựng ứng dụng theo dõi khoảng cách xe
Dịch vụ phát triển ứng dụng mobile giá rẻ - chất lượng
Bài trướcTất tần tật về Android App Bundle và Dynamic Feature
Bài tiếp theoHandler trong Android là gì? Bạn biết cách dùng chưa?
Tên đầy đủ là Dương Anh Sơn. Tốt nghiệp ĐH Bách Khoa Hà Nội. Mình bắt đầu nghiệp coder khi mà ra trường chẳng xin được việc đúng chuyên ngành. Mình tin rằng chỉ có chia sẻ kiến thức mới là cách học tập nhanh nhất. Các bạn góp ý bài viết của mình bằng cách comment bên dưới nhé !

18
Bình luận. Cùng nhau thảo luận nhé!

avatar
  Theo dõi bình luận  
Mới nhất Cũ nhất Nhiều voted nhất
Thông báo
Tứ Hải
Guest
Tứ Hải

Nếu sử dụng AndroidX thì code này sẽ bị lỗi chạy không được. Rất mong bạn hướng dẫn fixCode nếu sài AndroidX. Cám ơn bạn….

Tony
Guest
Tony

Nếu xác thực thế này thì chỉ là xác thực từ client. Khi xác thực xong ở client thì gửi lên server xác thực lại 1 lần nữa thì mới cho login

Thanh Sơn
Guest
Thanh Sơn

Cho mình xin source xác thực số điện thoại làm trên web php nhé. Cảm ơn bạn.

Thùy Trang
Guest
Thùy Trang

Đã like nhưng ko hiện

Nguyen Van Thanh
Guest
Nguyen Van Thanh

mVerificationId, mResendToken, mAuth là cái j vậy ạ, nó báo đỏ cái đó ạ

Toanvu
Guest
Toanvu

Code để dùng vào việc gì ad

TAn
Guest
TAn

Mình đã like rồi vẫn không thấy src code ạ? Mong bạn phản hồi sớm tới mình

beo
Guest
beo

mình like nhưng k hiện src ở đâu a?