Android SMS Verification App Like WhatsApp

Android OTP verification is the best method to avoid spamming.
Hello friends, in this tutorial we going to create a simple Android SMS Verification App.

You already seen this example in some popular applications like WhatsApp, Hike etc. They verify the user’s phone number by sending an OTP (One Time Password) to the phone number registered.

To avoid spamming this is the best way to confirm your user with their phone number. And that is why verifying user’s with their phone number is one of the most common feature for android app now days.

So in this tutorial we will create an Android SMS Verification App for registered users.

Before going further make sure that you have basic knowledge about android client-server communication.

Basic concept of OTP Verification:

  • To verify the user’s phone number we will send the verification code via SMS. For sending SMS we need an SMS API.
  • SMS’s are of two types
    • Promotional: It will not be sent to DND activated phone numbers. So for OTP or Phone verification we cannot use promotional SMS.
    • Transactional: It will be sent to all numbers, doesn’t matter a number has activated DND or not. In this tutorial I am using Transactional SMS.

This tutorial was divided into Two parts for easy understanding.

  • Server Side
  • Mobile App

First we take a look on  Server side (PHP,MySQL)

Server Side:

Here we’ll learn the server side part i.e. building the PHP, MySQL project by integrating the SMS gateway

1. Creating MySQL Database

For this project we need two tables. One is users table to store the user information and second one is otp_codes to store the user’s sms verification codes.

Create a database named android_otp.

CREATE DATABASE android_otp;

CREATE TABLE `otp_codes` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user_id` int(11) NOT NULL, `code` varchar(6) NOT NULL, `status` int(1) NOT NULL DEFAULT ‘0’, `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `user_id` (`user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; CREATE TABLE `users` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL, `email` varchar(250) NOT NULL, `mobile` varchar(10) NOT NULL, `apikey` varchar(32) NOT NULL, `status` int(1) NOT NULL DEFAULT ‘0’, `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=64 ; ALTER TABLE `otp_codes` ADD CONSTRAINT `otp_codes_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;

 

2. Creating PHP Project

Once you are done with database setup, let’s move to php project development

add below code to your Config.php file or create a new one.

Config.php

<?php
/**
* Database configuration
*/
define('DB_USERNAME', <db_user_name>);
define('DB_PASSWORD', <db_password>);
define('DB_HOST', <your_host>);
define('DB_NAME', 'android_otp);
define(SMS_GATEWAY_U_NAME', "<your_sms_gateway_user_name");
define(SMS_GATEWAY_U_PASS', "<your_sms_gateway_password");

define('USER_CREATED_SUCCESSFULLY', 0);
define('USER_CREATE_FAILED', 1);
define('USER_ALREADY_EXISTED', 2);
?>

Include the following code into your DBConnect.php file (This file handles the whole database connection.)

DBConnect.php

class DbConnect {

private $conn;

function __construct() {
}

/**
* Establishing database connection
* @return database connection handler
*/
function connect() {
include_once dirname(__FILE__) . '/Config.php';

// Connecting to mysql database
$this->conn = new mysqli(DB_HOST, DB_USERNAME, DB_PASSWORD, DB_NAME);

// Check for database connection error
if (mysqli_connect_errno()) {
echo "Failed to connect to MySQL: " . mysqli_connect_error();
exit;
}

// returing connection resource
return $this->conn;
}

}

?>

Then Create PHP file named DbHandler.php in include folder. This file contains the major functions to perform the OTP Verification operations onto database.

DbHandler.php

<?php

class DbHandler {

private $conn;

function __construct() {
require_once dirname(__FILE__) . '/DbConnect.php';
// opening db connection
$db = new DbConnect();
$this->conn = $db->connect();
}

/**
* Creating new user
* @param String $name User full name
* @param String $email User login email id
* @param String $mobile User mobile number
* @param String $otp user verificaiton code
*/
public function registerNewUser ($name, $email, $mobile, $otp) {
$response = array();

// First check if user already existed in db
if (!$this->isUserExists($mobile)) {

// Generating API key
$api_key = $this->generateApiKey();

// insert query
$stmt = $this->conn->prepare("INSERT INTO users(name, email, mobile, apikey, status) values(?, ?, ?, ?, 0)");
$stmt->bind_param("ssss", $name, $email, $mobile, $api_key);

$result = $stmt->execute();

$new_user_id = $stmt->insert_id;

$stmt->close();

// Check for successful insertion
if ($result) {

$otp_result = $this-> requestOTP ($new_user_id, $otp);

// User successfully inserted
return USER_CREATED_SUCCESSFULLY;
} else {
// Failed to create user
return USER_CREATE_FAILED;
}
} else {
// User with same email already existed in the db
return USER_ALREADY_EXISTED;
}

return $response;
}

public function requestOTP ($user_id, $otp) {

// delete the old otp if exists
$stmt = $this->conn->prepare("DELETE FROM otp_codes where user_id = ?");
$stmt->bind_param("i", $user_id);
$stmt->execute();

$stmt = $this->conn->prepare("INSERT INTO otp_codes(user_id, code, status) values(?, ?, 0)");
$stmt->bind_param("is", $user_id, $otp);

$result = $stmt->execute();

$stmt->close();

return $result;
}

/**
* Checking for duplicate user by mobile number
* @param String $email email to check in db
* @return boolean
*/
private function isUserExists($mobile) {
$stmt = $this->conn->prepare("SELECT id from users WHERE mobile = ? and status = 1");
$stmt->bind_param("s", $mobile);
$stmt->execute();
$stmt->store_result();
$num_rows = $stmt->num_rows;
$stmt->close();
return $num_rows > 0;
}

public function activateUser($otp) {
$stmt = $this->conn->prepare("SELECT u.id, u.name, u.email, u.mobile, u.apikey, u.status, u.created_at FROM users u, otp_codes WHERE otp_codes.code = ? AND otp_codes.user_id = u.id");
$stmt->bind_param("s", $otp);

if ($stmt->execute()) {
// $user = $stmt->get_result()->fetch_assoc();
$stmt->bind_result($id, $name, $email, $mobile, $apikey, $status, $created_at);

$stmt->store_result();

if ($stmt->num_rows > 0) {

$stmt->fetch();

// activate the user
$this->activateUserStatus($id);

$user = array();
$user["name"] = $name;
$user["email"] = $email;
$user["mobile"] = $mobile;
$user["apikey"] = $apikey;
$user["status"] = $status;
$user["created_at"] = $created_at;

$stmt->close();

return $user;
} else {
return NULL;
}
} else {
return NULL;
}

return $result;
}

public function activateUserStatus($user_id){
$stmt = $this->conn->prepare("UPDATE users set status = 1 where id = ?");
$stmt->bind_param("i", $user_id);

$stmt->execute();

$stmt = $this->conn->prepare("UPDATE otp_codes set status = 1 where user_id = ?");
$stmt->bind_param("i", $user_id);

$stmt->execute();
}

/**
* Generating random Unique MD5 String for user Api key
*/
private function generateApiKey() {
return md5(uniqid(rand(), true));
}
}
?>

Webservice: (API to connect mobile with our server)

In your project’s root directory, create a file named register.php.
In below code

First we get the name, email and mobile number those were sent from the android device as a POST parameters.

We create an entry in users table by calling registerNewUser() function. Initially the user status will be 0 which indicate the user is inactive. This status will be changed to 1 when the user verifies the OTP.

Once the user row is created in table, we request for an OTP SMS to the entered mobile number by calling requestOTP() method.

sendSms() method will make a call to your SMS gateway to send SMS with a 6 digits OTP to the users mobile number.

register.php

<?php

include './include/DbHandler.php';
$db = new DbHandler();

$response = array();

if (isset($_POST['mobile']) && $_POST['mobile'] != '') {

$name = $_POST['name'];
$email = $_POST['email'];
$mobile = $_POST['mobile'];

$otp = rand(100000, 999999);

$res = $db->createUser($name, $email, $mobile, $otp);

if ($res == USER_CREATED_SUCCESSFULLY) {

// send sms
sendSms($mobile, $otp);

$response["error"] = false;
$response["message"] = "OTP SMS sent to your registed mobile number.";
} else if ($res == USER_CREATE_FAILED) {
$response["error"] = true;
$response["message"] = "Sorry! Error while registering";
} else if ($res == USER_ALREADY_EXISTED) {
$response["error"] = true;
$response["message"] = "Mobile number already existed!";
}
} else {
$response["error"] = true;
$response["message"] = "Sorry! mobile number is not valid or missing.";
}

echo json_encode($response);

function sendSms($mobile, $otp) {

$otp_prefix = ':';

//Your message to send, Add URL encoding here.
$message = urlencode("Your OPT is '$otp_prefix $otp'");
/* here implement your sms gateway code to request a new message of OTP */
}
?>

Now we need to create another web service for verifying OTP,  Create a php file named verify_otp.php with below content.

In the below code

 The OTP will be received from the android device as a POST param.

The user who matches with OTP will fetched from the users table.

Then the user status will be set to 1 in, both users and sms_codes table which makes the user active.

The above two steps are implemented in enableUser() function.

verify_otp.php

<?php

include './include/DbHandler.php';
$db = new DbHandler();

$response = array();
$response["error"] = false;

if (isset($_POST['otp']) && $_POST['otp'] != '') {
$otp = $_POST['otp'];

$user = $db->activateUser($otp);

if ($user != NULL) {

$response["message"] = "User created successfully!";
$response["profile"] = $user;
} else {
$response["message"] = "Invalid OTP";
}

} else {
$response["message"] = "Sorry! OTP is missing.";
}

echo json_encode($response);
?>

Sample Responce from server:

 

register.php

{ "error": false, "message": "SMS request is initiated! You will receive shortly." }

 

verify_otp.php

{ "error": false, "message": "User created successfully!", "profile": { "name": "appsinfoway", "email": "support@appsinfoway.com", "mobile": "1234568790", "apikey": "3430558as23xs3454324m324o389dn", "status": 1, "created_at": "2015-07-30 22:18:59" } }