Edit Template

In today’s digital world, users want fast and secure login systems. Nobody likes remembering long passwords or waiting for password reset emails. That’s why OTP (One-Time Password) verification systems are becoming extremely popular for WordPress websites.

Whether you run a course-selling platform, membership website, eCommerce store, or service-based business, OTP login can improve both security and user experience.

In this blog, we’ll understand:


What is OTP Verification?

OTP (One-Time Password) verification is a login or signup system where users receive a temporary code on their mobile number. They enter the code to verify their identity.

Instead of using traditional usernames and passwords, users can simply log in using their phone numbers.

Example:

  1. User enters mobile number
  2. OTP is sent via SMS
  3. User enters OTP
  4. User gets logged in instantly

This method is widely used by apps like banking platforms, food delivery apps, eCommerce websites, and social media platforms.


Benefits of OTP Login for WordPress Websites

1. Faster Login Experience

Users don’t need to remember passwords. They can log in within seconds using OTP verification.

This improves user convenience and reduces login friction.


2. Better Security

Passwords can be guessed, leaked, or reused. OTP verification adds an extra security layer because the OTP works only once and expires quickly.


3. Reduce Fake Registrations

OTP verification ensures that users enter real mobile numbers during signup.

This helps reduce spam accounts and fake registrations.


4. Higher Conversion Rates

A simple OTP-based login system can increase signup completion rates because users prefer quick authentication methods.

Especially useful for:


5. Password Reset Problems are Eliminated

Since users log in using OTP, they don’t need to remember passwords or request password reset emails repeatedly.


What is DLT Registration?

DLT stands for Distributed Ledger Technology.

In India, telecom authorities introduced DLT regulations to reduce spam SMS and fraudulent messaging.

Under TRAI regulations, businesses sending SMS messages through telecom networks usually need:

This process is commonly known as DLT Registration.


Why Do Most OTP Providers Require DLT?

Most SMS gateway providers in India use telecom routes that are directly connected to Indian operators.

Because of TRAI regulations, these providers require businesses to complete DLT verification before sending:

Without DLT approval, SMS delivery may fail or messages may get blocked.


Problems With DLT Registration

Although DLT helps reduce spam, it creates problems for many small website owners and developers.

Some common issues include:

For developers testing OTP systems or small businesses starting out, DLT can become a major hurdle.


How Message Central is Different

Message Central provides a simpler way to implement OTP verification systems.

One of the biggest advantages of Message Central is that developers can integrate OTP functionality without going through the complicated DLT registration process for basic OTP workflows.

This makes it extremely useful for:


Benefits of Using Message Central

Easy API Integration

Message Central provides simple API endpoints that can be integrated into WordPress websites easily.


Fast OTP Delivery

OTP messages are delivered quickly, providing a smooth login experience for users.


Beginner-Friendly

Compared to traditional SMS gateway providers, setup is much simpler.


Perfect for WordPress OTP Systems

You can use it with:


No Complex DLT Setup for Basic OTP Workflows

This is the biggest reason many developers prefer Message Central for OTP verification systems.


WordPress OTP Verification Using Message Central

Now comes the practical part.

In the next section, we’ll integrate Message Central OTP verification into a WordPress website using custom code.

We will create:

You can add this functionality to:


What We Will Need

Before starting, make sure you have:

1. WordPress Website

A working WordPress installation.


2. Message Central Account

Create an account on Message Central and get:


3. Access to functions.php

We’ll add custom code inside:


Features We’ll Build

Our OTP system will include:

Install WPCode – Insert Headers and Footers + Custom Code Snippets – WordPress Code Manager

/**
 * Plugin Name: WB OTP Login
 * Description: OTP based login using MessageCentral with full admin customization
 * Version: 2.0
 */

// ============================================
// AJAX: Update New User Profile
// ============================================
add_action('wp_ajax_wb_update_profile', 'wb_update_profile');
add_action('wp_ajax_nopriv_wb_update_profile', 'wb_update_profile');
function wb_update_profile() {
    $name = sanitize_text_field($_POST['name'] ?? '');
    $mobile = sanitize_text_field($_POST['mobile'] ?? '');
    
    if (empty($name) || strlen($name) < 2) {
        wp_send_json_error('Please enter a valid name');
    }
    
    $users = get_users([
        'meta_key'   => 'mobile_number',
        'meta_value' => $mobile,
        'number'     => 1
    ]);
    
    if (empty($users)) {
        wp_send_json_error('User not found');
    }
    
    $user_id = $users[0]->ID;
    wp_update_user([
        'ID'           => $user_id,
        'display_name' => $name,
        'first_name'   => $name,
    ]);
    
    wp_send_json_success('Profile updated');
}

// ============================================
// LOGIN SHORTCODE - DYNAMIC STYLES
// ============================================
function wb_login_shortcode() {
    if (is_user_logged_in()) {
        $redirect = wb_get_setting('redirect_url', '/dashboard/');
        wp_redirect(home_url($redirect));
        exit;
    }
    
    add_filter('show_admin_bar', '__return_false');
    
    // Get all settings
    $logo_url = wb_get_setting('logo_url');
    $bg_color_1 = wb_get_setting('bg_color_1', '#0f6c82');
    $bg_color_2 = wb_get_setting('bg_color_2', '#0a3f5c');
    $card_bg = wb_get_setting('card_bg', '#f1f5f9');
    $heading_color = wb_get_setting('heading_color', '#1f2937');
    $btn_bg = wb_get_setting('btn_bg', 'linear-gradient(to right, #000, #333)');
    $btn_text_color = wb_get_setting('btn_text_color', '#ffffff');
    $input_border = wb_get_setting('input_border', '#d1d5db');
    $custom_css = wb_get_setting('custom_css', '');
    $redirect_url = wb_get_setting('redirect_url', '/dashboard/');
    $register_url = wb_get_setting('register_url', '');
    $forgot_url = wb_get_setting('forgot_url', '');
    
    ob_start(); 
    ?>
    <div class="wb-login-container">
        <div class="wb-login-box">
            <?php if ($logo_url): ?>
            <div class="wb-login-logo">
                <img src="<?php echo esc_url($logo_url); ?>" alt="Logo">
            </div>
            <?php endif; ?>
            
            <h2><?php echo esc_html(wb_get_setting('heading_text', 'WELCOME BACK')); ?></h2>

            <!-- Step 1: Mobile Input -->
            <div id="step-mobile">
                <div class="wb-input-wrap">
                    <input type="tel" id="mobileNumber" placeholder="Enter 10-digit number" maxlength="10">
                </div>
                <button id="sendOtpBtn" class="wb-btn">Send OTP</button>
            </div>

            <!-- Step 2: OTP Input -->
            <div id="step-otp" style="display:none;">
                <p class="otp-sent-text">OTP sent to <span id="displayMobile"></span></p>
                <input type="text" id="otpCode" placeholder="Enter 6-digit OTP" maxlength="6">
                <button id="verifyOtpBtn" class="wb-btn">Verify OTP</button>
                <button type="button" class="wb-btn wb-btn-secondary" onclick="resendOtp()">Resend OTP</button>
                <p class="change-number"><a href="#" onclick="changeNumber()">Change number</a></p>
            </div>

            <!-- Step 3: Loading -->
            <div id="step-loading" style="display:none;">
                <div class="wb-spinner"></div>
                <p>Logging you in...</p>
            </div>

            <div id="loginMessage"></div>
            
            <!-- Links -->
            <div class="wb-login-links">
                <?php if ($register_url): ?>
                    <a href="<?php echo esc_url($register_url); ?>" class="wb-link">Create Account</a>
                <?php endif; ?>
                <?php if ($forgot_url): ?>
                    <a href="<?php echo esc_url($forgot_url); ?>" class="wb-link">Forgot Password?</a>
                <?php endif; ?>
            </div>
        </div>
    </div>

    <script>
    document.addEventListener("DOMContentLoaded", function () {
        let mobileNumber = '';
        const sendBtn = document.getElementById("sendOtpBtn");
        const verifyBtn = document.getElementById("verifyOtpBtn");
        const ajaxUrl = '<?php echo esc_url(admin_url('admin-ajax.php')); ?>';

        sendBtn.addEventListener('click', async function() {
            mobileNumber = document.getElementById("mobileNumber").value.trim();
            if (!/^[0-9]{10}$/.test(mobileNumber)) {
                showMsg("Please enter a valid 10-digit mobile number", "error");
                return;
            }
            sendBtn.disabled = true;
            sendBtn.innerHTML = '<span class="wb-spinner-small"></span> Sending...';

            const formData = new URLSearchParams();
            formData.append('action', 'wb_mc_send_otp');
            formData.append('mobile', mobileNumber);
            formData.append('nonce', '<?php echo wp_create_nonce('wb_firebase_nonce'); ?>');

            try {
                const response = await fetch(ajaxUrl, {
                    method: "POST",
                    headers: { "Content-Type": "application/x-www-form-urlencoded" },
                    body: formData
                });
                const data = await response.json();

                if (data.success) {
                    document.getElementById("step-mobile").style.display = "none";
                    document.getElementById("step-otp").style.display = "block";
                    document.getElementById("displayMobile").textContent = "+91 " + mobileNumber;
                    showMsg("OTP sent successfully!", "success");
                } else {
                    showMsg(data.data || "Failed to send OTP", "error");
                    sendBtn.disabled = false;
                    sendBtn.innerHTML = "Send OTP";
                }
            } catch (err) {
                showMsg("Network error. Please try again.", "error");
                sendBtn.disabled = false;
                sendBtn.innerHTML = "Send OTP";
            }
        });

        verifyBtn.addEventListener('click', async function() {
            const otp = document.getElementById("otpCode").value.trim();
            if (!/^[0-9]{4,8}$/.test(otp)) {
                showMsg("Please enter a valid OTP", "error");
                return;
            }
            verifyBtn.disabled = true;
            verifyBtn.innerHTML = '<span class="wb-spinner-small"></span> Verifying...';

            const formData = new URLSearchParams();
            formData.append('action', 'wb_mc_verify_otp');
            formData.append('mobile', mobileNumber);
            formData.append('otp', otp);
            formData.append('nonce', '<?php echo wp_create_nonce('wb_firebase_nonce'); ?>');

            try {
                const response = await fetch(ajaxUrl, {
                    method: "POST",
                    headers: { "Content-Type": "application/x-www-form-urlencoded" },
                    body: formData
                });
                const data = await response.json();

                if (data.success && data.data) {
                    showMsg("OTP verified! Logging in...", "success");
                    document.getElementById("step-otp").style.display = "none";
                    document.getElementById("step-loading").style.display = "block";

                    if (data.data.is_new_user) {
                        showNewUserPopup(data.data.redirect);
                    } else {
                        const redirectUrl = data.data.redirect || '<?php echo esc_js(home_url($redirect_url)); ?>';
                        window.location.href = redirectUrl;
                    }
                } else {
                    showMsg(data.data || "Invalid OTP. Please try again.", "error");
                    verifyBtn.disabled = false;
                    verifyBtn.innerHTML = "Verify OTP";
                }
            } catch (err) {
                showMsg("Connection error. Please try again.", "error");
                verifyBtn.disabled = false;
                verifyBtn.innerHTML = "Verify OTP";
            }
        });

        function showNewUserPopup(redirectUrl) {
            document.getElementById("step-loading").style.display = "none";
            const popup = document.createElement('div');
            popup.className = 'wb-popup-overlay';
            popup.id = 'newUserPopup';
            popup.innerHTML = `
                <div class="wb-popup">
                    <h3>Welcome! Complete Your Profile</h3>
                    <p>Please enter your name to complete registration:</p>
                    <input type="text" id="newUserName" placeholder="Your Full Name" maxlength="50">
                    <div id="popupError" style="color: #f87171; margin: 10px 0; font-size: 14px;"></div>
                    <button class="wb-btn" onclick="completeRegistration('${redirectUrl}')">Complete & Continue</button>
                </div>
            `;
            document.body.appendChild(popup);
            document.getElementById('newUserName').focus();
        }

        window.completeRegistration = async function(redirectUrl) {
            const nameInput = document.getElementById('newUserName');
            const name = nameInput.value.trim();
            const errorDiv = document.getElementById('popupError');
            
            if (!name || name.length < 2) {
                errorDiv.textContent = "Please enter a valid name (at least 2 characters)";
                return;
            }

            const btn = document.querySelector('#newUserPopup .wb-btn');
            btn.disabled = true;
            btn.innerHTML = '<span class="wb-spinner-small"></span> Saving...';

            const formData = new URLSearchParams();
            formData.append('action', 'wb_update_profile');
            formData.append('name', name);
            formData.append('mobile', mobileNumber);

            try {
                const response = await fetch(ajaxUrl, {
                    method: "POST",
                    headers: { "Content-Type": "application/x-www-form-urlencoded" },
                    body: formData
                });
                const data = await response.json();
                
                if (data.success) {
                    window.location.href = redirectUrl || '<?php echo esc_js(home_url($redirect_url)); ?>';
                } else {
                    errorDiv.textContent = data.data || "Failed to save profile";
                    btn.disabled = false;
                    btn.innerHTML = 'Complete & Continue';
                }
            } catch (err) {
                errorDiv.textContent = "Connection error. Please try again.";
                btn.disabled = false;
                btn.innerHTML = 'Complete & Continue';
            }
        };

        window.resendOtp = async function() {
            document.getElementById("otpCode").value = "";
            showMsg("Resending OTP...", "info");
            const formData = new URLSearchParams();
            formData.append('action', 'wb_mc_send_otp');
            formData.append('mobile', mobileNumber);
            formData.append('nonce', '<?php echo wp_create_nonce('wb_firebase_nonce'); ?>');

            try {
                const response = await fetch(ajaxUrl, {
                    method: "POST",
                    headers: { "Content-Type": "application/x-www-form-urlencoded" },
                    body: formData
                });
                const data = await response.json();
                if (data.success) {
                    showMsg("OTP resent successfully!", "success");
                } else {
                    showMsg(data.data || "Failed to resend", "error");
                }
            } catch (err) {
                showMsg("Network error. Please try again.", "error");
            }
        };

        window.changeNumber = function() {
            document.getElementById("step-otp").style.display = "none";
            document.getElementById("step-mobile").style.display = "block";
            document.getElementById("otpCode").value = "";
            document.getElementById("mobileNumber").value = "";
            sendBtn.disabled = false;
            sendBtn.innerHTML = "Send OTP";
            showMsg("", "");
            return false;
        };

        function showMsg(msg, type) {
            const el = document.getElementById("loginMessage");
            el.textContent = msg;
            el.className = type;
        }
    });
    </script>

    <style>
    /* Base Styles */
    html { margin-top: 0 !important; }
    #wpadminbar { display: none !important; }
    
    .wb-login-container {
        min-height: 100vh;
        display: flex;
        justify-content: center;
        align-items: center;
        background: linear-gradient(180deg, <?php echo esc_attr($bg_color_1); ?>, <?php echo esc_attr($bg_color_2); ?>);
        padding: 20px;
    }

    .wb-login-box {
        background: <?php echo esc_attr($card_bg); ?>;
        padding: 30px 25px;
        border-radius: 25px;
        width: 100%;
        max-width: 360px;
        text-align: center;
        box-shadow: 0 20px 40px rgba(0,0,0,0.3);
    }

    .wb-login-logo {
        margin: 0 auto 15px;
        text-align: center;
    }

    .wb-login-logo img {
        max-width: 200px;
        max-height: 70px;
        width: auto;
        height: auto;
    }

    .wb-login-box h2 {
        font-size: 22px;
        font-weight: 700;
        color: <?php echo esc_attr($heading_color); ?>;
        margin-bottom: 20px;
        letter-spacing: 1px;
    }

    .wb-input-wrap {
        position: relative;
        text-align: left;
    }

    #mobileNumber {
        width: 100%;
        padding: 14px 14px 14px 60px;
        border-radius: 12px;
        border: 1px solid <?php echo esc_attr($input_border); ?>;
        font-size: 15px;
        background: #fff;
        color: black;
        box-sizing: border-box;
    }

    .wb-input-wrap::before {
        content: "+91";
        position: absolute;
        left: 14px;
        top: 14px;
        font-weight: bold;
        color: #374151;
        z-index: 2;
    }

    .wb-btn {
        width: 100%;
        padding: 14px;
        border-radius: 12px;
        border: none;
        font-weight: 600;
        font-size: 16px;
        background: <?php echo esc_attr($btn_bg); ?>;
        color: <?php echo esc_attr($btn_text_color); ?>;
        margin-top: 15px;
        cursor: pointer;
        transition: 0.3s;
    }

    .wb-btn:hover {
        opacity: 0.9;
        transform: translateY(-1px);
    }

    .wb-btn-secondary {
        background: transparent;
        border: 1px solid #ccc;
        color: #333;
    }

    #step-otp input {
        width: 100%;
        padding: 14px;
        border-radius: 12px;
        border: 1px solid <?php echo esc_attr($input_border); ?>;
        margin-bottom: 10px;
        box-sizing: border-box;
    }

    .otp-sent-text {
        color: #555;
        font-size: 14px;
        margin-bottom: 10px;
    }

    #loginMessage {
        margin-top: 10px;
        font-size: 14px;
        min-height: 20px;
    }

    #loginMessage.success { color: #16a34a; }
    #loginMessage.error { color: #dc2626; }
    #loginMessage.info { color: #0f6c82; }

    .wb-spinner-small {
        width: 16px;
        height: 16px;
        border: 2px solid rgba(255,255,255,0.3);
        border-top: 2px solid <?php echo esc_attr($btn_text_color); ?>;
        border-radius: 50%;
        display: inline-block;
        animation: spin 0.8s linear infinite;
        margin-right: 8px;
        vertical-align: middle;
    }

    @keyframes spin {
        100% { transform: rotate(360deg); }
    }

    .wb-login-links {
        margin-top: 20px;
        display: flex;
        justify-content: center;
        gap: 20px;
        flex-wrap: wrap;
    }

    .wb-login-links a {
        color: #555;
        font-size: 13px;
        text-decoration: none;
        transition: color 0.2s;
    }

    .wb-login-links a:hover {
        color: <?php echo esc_attr($heading_color); ?>;
        text-decoration: underline;
    }

    .change-number {
        margin-top: 10px;
        font-size: 13px;
    }

    .change-number a {
        color: #0f6c82;
        text-decoration: none;
    }

    /* Popup */
    .wb-popup-overlay {
        position: fixed;
        top: 0; left: 0; right: 0; bottom: 0;
        background: rgba(0,0,0,0.6);
        display: flex;
        align-items: center;
        justify-content: center;
        z-index: 9999;
    }
    
    .wb-popup {
        background: #fff;
        padding: 30px;
        border-radius: 16px;
        width: 90%;
        max-width: 360px;
        text-align: center;
    }
    
    .wb-popup h3 {
        margin-bottom: 10px;
        color: #1f2937;
    }
    
    .wb-popup input {
        width: 100%;
        padding: 12px;
        border-radius: 8px;
        border: 1px solid #d1d5db;
        margin: 10px 0;
        font-size: 15px;
        box-sizing: border-box;
    }

    /* Custom CSS from admin */
    <?php echo wp_strip_all_tags($custom_css); ?>

    @media (max-width: 480px) {
        .wb-login-box {
            padding: 25px 20px;
            border-radius: 20px;
        }
    }
    </style>
    <?php
    return ob_get_clean();
}
add_shortcode('wb_login', 'wb_login_shortcode');

// ============================================
// MESSAGECENTRAL API FUNCTIONS
// ============================================

function wb_get_setting($key, $default = '') {
    $settings = get_option('wb_login_settings', []);
    return isset($settings[$key]) && !empty($settings[$key]) ? $settings[$key] : $default;
}

function wb_mc_get_auth_token() {
    $customer_id = wb_get_setting('mc_customer_id');
    $email = wb_get_setting('mc_email');
    $key = wb_get_setting('mc_key');
    $country = wb_get_setting('mc_country', 'IN');
    
    if (empty($customer_id) || empty($email) || empty($key)) {
        error_log('MessageCentral: Missing credentials');
        return false;
    }
    
    $url = add_query_arg([
        'country'    => $country,
        'customerId' => $customer_id,
        'email'      => $email,
        'key'        => $key,
        'scope'      => 'NEW'
    ], 'https://cpaas.messagecentral.com/auth/v1/authentication/token');

    $response = wp_remote_get($url, [
        'headers' => ['accept' => '*/*'],
        'timeout' => 30,
        'sslverify' => true
    ]);

    if (is_wp_error($response)) {
        error_log('MessageCentral Token Error: ' . $response->get_error_message());
        return false;
    }

    $body = json_decode(wp_remote_retrieve_body($response), true);
    return $body['token'] ?? false;
}

// AJAX: Send OTP
add_action('wp_ajax_wb_mc_send_otp', 'wb_mc_send_otp');
add_action('wp_ajax_nopriv_wb_mc_send_otp', 'wb_mc_send_otp');

function wb_mc_send_otp() {
    check_ajax_referer('wb_firebase_nonce', 'nonce');

    $mobile = sanitize_text_field($_POST['mobile'] ?? '');
    if (!preg_match('/^[0-9]{10}$/', $mobile)) {
        wp_send_json_error('Please enter a valid 10-digit mobile number');
    }

    $token = wb_mc_get_auth_token();
    if (!$token) {
        wp_send_json_error('Unable to connect to SMS gateway. Please check credentials.');
    }

    $country_code = wb_get_setting('mc_country_code', '91');
    
    $url = add_query_arg([
        'countryCode'  => $country_code,
        'flowType'     => 'SMS',
        'mobileNumber' => $mobile,
        'otpLength'    => 6
    ], 'https://cpaas.messagecentral.com/verification/v3/send');

    $response = wp_remote_post($url, [
        'headers' => [
            'accept'    => '*/*',
            'authToken' => $token
        ],
        'timeout' => 30,
        'sslverify' => true
    ]);

    if (is_wp_error($response)) {
        wp_send_json_error('Failed to send OTP. Please try again.');
    }

    $body = json_decode(wp_remote_retrieve_body($response), true);
    $data = $body['data'] ?? [];

    if (($body['responseCode'] ?? 0) == 200 && !empty($data['verificationId'])) {
        $transient_key = 'wb_mc_' . md5($mobile . ($_SERVER['REMOTE_ADDR'] ?? '') . ($_SERVER['HTTP_USER_AGENT'] ?? ''));
        set_transient($transient_key, $data['verificationId'], 5 * MINUTE_IN_SECONDS);
        
        wp_send_json_success(['message' => 'OTP sent successfully']);
    } else {
        $error = $data['errorMessage'] ?? 'Unknown error from SMS provider';
        wp_send_json_error($error);
    }
}

// AJAX: Verify OTP
add_action('wp_ajax_wb_mc_verify_otp', 'wb_mc_verify_otp');
add_action('wp_ajax_nopriv_wb_mc_verify_otp', 'wb_mc_verify_otp');

function wb_mc_verify_otp() {
    check_ajax_referer('wb_firebase_nonce', 'nonce');

    $mobile = sanitize_text_field($_POST['mobile'] ?? '');
    $otp    = sanitize_text_field($_POST['otp'] ?? '');

    if (!preg_match('/^[0-9]{10}$/', $mobile) || !preg_match('/^[0-9]{4,8}$/', $otp)) {
        wp_send_json_error('Invalid mobile number or OTP');
    }

    $transient_key = 'wb_mc_' . md5($mobile . ($_SERVER['REMOTE_ADDR'] ?? '') . ($_SERVER['HTTP_USER_AGENT'] ?? ''));
    $verification_id = get_transient($transient_key);

    if (!$verification_id) {
        wp_send_json_error('OTP expired. Please request a new one.');
    }

    $token = wb_mc_get_auth_token();
    if (!$token) {
        wp_send_json_error('Unable to connect to SMS gateway.');
    }

    $url = add_query_arg([
        'verificationId' => $verification_id,
        'code'           => $otp
    ], 'https://cpaas.messagecentral.com/verification/v3/validateOtp');

    $response = wp_remote_get($url, [
        'headers' => [
            'accept'    => '*/*',
            'authToken' => $token
        ],
        'timeout' => 30,
        'sslverify' => true
    ]);

    if (is_wp_error($response)) {
        wp_send_json_error('Verification failed. Please try again.');
    }

    $body = json_decode(wp_remote_retrieve_body($response), true);
    $data = $body['data'] ?? [];

    if (($body['responseCode'] ?? 0) == 200 && 
        !empty($data['verificationStatus']) && 
        $data['verificationStatus'] === 'VERIFICATION_COMPLETED') {
        
        delete_transient($transient_key);

        $users = get_users([
            'meta_key'   => 'mobile_number',
            'meta_value' => $mobile,
            'number'     => 1
        ]);

        $is_new_user = false;

        if (!empty($users)) {
            $user_id = $users[0]->ID;
        } else {
            $is_new_user = true;
            $username = 'user_' . $mobile . '_' . wp_rand(1000, 9999);
            
            $user_id = wp_insert_user([
                'user_login'   => $username,
                'user_pass'    => wp_generate_password(20),
                'user_nicename'=> $username,
                'display_name' => 'User ' . $mobile,
                'role'         => 'subscriber'
            ]);

            if (is_wp_error($user_id)) {
                wp_send_json_error('Failed to create user: ' . $user_id->get_error_message());
            }

            update_user_meta($user_id, 'mobile_number', $mobile);
        }

        wp_set_current_user($user_id);
        wp_set_auth_cookie($user_id, true);
        
        $user_obj = get_user_by('id', $user_id);
        do_action('wp_login', $user_obj->user_login, $user_obj);

        $redirect_path = wb_get_setting('redirect_url', '/dashboard/');
        $redirect_url = home_url($redirect_path);
        
        $dashboard_page = get_page_by_path(trim($redirect_path, '/'));
        if (!$dashboard_page) {
            $redirect_url = home_url('/');
        }

        wp_send_json_success([
            'is_new_user' => $is_new_user,
            'user_id'     => $user_id,
            'redirect'    => $redirect_url
        ]);

    } else {
        $error = $data['errorMessage'] ?? 'Invalid OTP. Please try again.';
        wp_send_json_error($error);
    }
}

// ============================================
// ADMIN SETTINGS PAGE
// ============================================

// Add admin menu
add_action('admin_menu', 'wb_login_admin_menu');
function wb_login_admin_menu() {
    add_menu_page(
        'WB OTP Login Settings',
        'OTP Login',
        'manage_options',
        'wb-otp-login',
        'wb_login_settings_page',
        'dashicons-phone',
        80
    );
}

// Register settings
add_action('admin_init', 'wb_login_register_settings');
function wb_login_register_settings() {
    register_setting('wb_login_settings', 'wb_login_settings', 'wb_login_sanitize_settings');
    
    // Credentials Section
    add_settings_section('wb_credentials_section', '📱 MessageCentral API Credentials', null, 'wb-otp-login');
    add_settings_field('mc_customer_id', 'Customer ID', 'wb_render_text_field', 'wb-otp-login', 'wb_credentials_section', ['key' => 'mc_customer_id', 'placeholder' => 'C-XXXXXXXXXX']);
    add_settings_field('mc_email', 'Email', 'wb_render_text_field', 'wb-otp-login', 'wb_credentials_section', ['key' => 'mc_email', 'placeholder' => 'moc.liameobfsctd@ruoy']);
    add_settings_field('mc_key', 'API Key (Base64)', 'wb_render_text_field', 'wb-otp-login', 'wb_credentials_section', ['key' => 'mc_key', 'placeholder' => 'Base64 encoded key']);
    add_settings_field('mc_country', 'Country Code (ISO)', 'wb_render_text_field', 'wb-otp-login', 'wb_credentials_section', ['key' => 'mc_country', 'placeholder' => 'IN']);
    add_settings_field('mc_country_code', 'Dial Code', 'wb_render_text_field', 'wb-otp-login', 'wb_credentials_section', ['key' => 'mc_country_code', 'placeholder' => '91']);
    
    // Appearance Section
    add_settings_section('wb_appearance_section', '🎨 Appearance Settings', null, 'wb-otp-login');
    add_settings_field('logo_url', 'Logo URL', 'wb_render_text_field', 'wb-otp-login', 'wb_appearance_section', ['key' => 'logo_url', 'placeholder' => 'https://example.com/logo.png']);
    add_settings_field('heading_text', 'Heading Text', 'wb_render_text_field', 'wb-otp-login', 'wb_appearance_section', ['key' => 'heading_text', 'placeholder' => 'WELCOME BACK']);
    add_settings_field('bg_color_1', 'Background Gradient (Top)', 'wb_render_color_field', 'wb-otp-login', 'wb_appearance_section', ['key' => 'bg_color_1']);
    add_settings_field('bg_color_2', 'Background Gradient (Bottom)', 'wb_render_color_field', 'wb-otp-login', 'wb_appearance_section', ['key' => 'bg_color_2']);
    add_settings_field('card_bg', 'Card Background', 'wb_render_color_field', 'wb-otp-login', 'wb_appearance_section', ['key' => 'card_bg']);
    add_settings_field('heading_color', 'Heading Color', 'wb_render_color_field', 'wb-otp-login', 'wb_appearance_section', ['key' => 'heading_color']);
    add_settings_field('btn_bg', 'Button Background', 'wb_render_text_field', 'wb-otp-login', 'wb_appearance_section', ['key' => 'btn_bg', 'placeholder' => '#000000 or linear-gradient(...)']);
    add_settings_field('btn_text_color', 'Button Text Color', 'wb_render_color_field', 'wb-otp-login', 'wb_appearance_section', ['key' => 'btn_text_color']);
    add_settings_field('input_border', 'Input Border Color', 'wb_render_color_field', 'wb-otp-login', 'wb_appearance_section', ['key' => 'input_border']);
    
    // Links Section
    add_settings_section('wb_links_section', '🔗 Page Links & Redirects', null, 'wb-otp-login');
    add_settings_field('redirect_url', 'Post-Login Redirect URL', 'wb_render_text_field', 'wb-otp-login', 'wb_links_section', ['key' => 'redirect_url', 'placeholder' => '/dashboard/']);
    add_settings_field('register_url', 'Register Page URL', 'wb_render_text_field', 'wb-otp-login', 'wb_links_section', ['key' => 'register_url', 'placeholder' => '/register/']);
    add_settings_field('forgot_url', 'Forgot Password URL', 'wb_render_text_field', 'wb-otp-login', 'wb_links_section', ['key' => 'forgot_url', 'placeholder' => '/forgot-password/']);
    
    // Custom CSS Section
    add_settings_section('wb_css_section', '🎨 Custom CSS', null, 'wb-otp-login');
    add_settings_field('custom_css', 'Additional CSS', 'wb_render_textarea_field', 'wb-otp-login', 'wb_css_section', ['key' => 'custom_css']);
}

// Render functions
function wb_render_text_field($args) {
    $settings = get_option('wb_login_settings', []);
    $value = isset($settings[$args['key']]) ? $settings[$args['key']] : '';
    $placeholder = isset($args['placeholder']) ? $args['placeholder'] : '';
    echo sprintf('<input type="text" name="wb_login_settings[%s]" value="%s" class="regular-text" placeholder="%s">', 
        esc_attr($args['key']), esc_attr($value), esc_attr($placeholder));
}

function wb_render_color_field($args) {
    $settings = get_option('wb_login_settings', []);
    $value = isset($settings[$args['key']]) ? $settings[$args['key']] : '';
    echo sprintf('<input type="text" name="wb_login_settings[%s]" value="%s" class="wb-color-picker" data-default-color="%s">', 
        esc_attr($args['key']), esc_attr($value), esc_attr($value));
}

function wb_render_textarea_field($args) {
    $settings = get_option('wb_login_settings', []);
    $value = isset($settings[$args['key']]) ? $settings[$args['key']] : '';
    echo sprintf('<textarea name="wb_login_settings[%s]" rows="8" class="large-text code" style="font-family: monospace;">%s</textarea>', 
        esc_attr($args['key']), esc_textarea($value));
}

// Sanitize settings
function wb_login_sanitize_settings($input) {
    $output = [];
    
    $text_fields = ['mc_customer_id', 'mc_email', 'mc_key', 'mc_country', 'mc_country_code', 
                    'logo_url', 'heading_text', 'btn_bg', 'redirect_url', 'register_url', 'forgot_url'];
    foreach ($text_fields as $field) {
        $output[$field] = isset($input[$field]) ? sanitize_text_field($input[$field]) : '';
    }
    
    $color_fields = ['bg_color_1', 'bg_color_2', 'card_bg', 'heading_color', 'btn_text_color', 'input_border'];
    foreach ($color_fields as $field) {
        $output[$field] = isset($input[$field]) ? sanitize_hex_color($input[$field]) : '';
    }
    
    $output['custom_css'] = isset($input['custom_css']) ? wp_strip_all_tags($input['custom_css']) : '';
    
    return $output;
}

// Enqueue admin scripts
add_action('admin_enqueue_scripts', 'wb_login_admin_scripts');
function wb_login_admin_scripts($hook) {
    if ($hook !== 'toplevel_page_wb-otp-login') return;
    
    wp_enqueue_style('wp-color-picker');
    wp_enqueue_script('wp-color-picker');
    wp_add_inline_script('wp-color-picker', '
        jQuery(document).ready(function($) {
            $(".wb-color-picker").wpColorPicker();
        });
    ');
    
    wp_enqueue_style('wb-admin-style', false);
    wp_add_inline_style('wp-admin', '
        .wb-admin-header {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 20px;
            margin: 20px 0;
            border-radius: 8px;
        }
        .wb-shortcode-box {
            background: #f0f9ff;
            border: 2px dashed #0ea5e9;
            border-radius: 8px;
            padding: 15px;
            margin: 20px 0;
            text-align: center;
        }
        .wb-shortcode-code {
            background: #1e293b;
            color: #38bdf8;
            padding: 10px 20px;
            border-radius: 6px;
            font-family: monospace;
            font-size: 16px;
            display: inline-block;
            cursor: pointer;
        }
        .wb-shortcode-code:hover {
            background: #0f172a;
        }
        .wb-cred-help {
            background: #fef3c7;
            border-left: 4px solid #f59e0b;
            padding: 10px 15px;
            margin: 15px 0;
            border-radius: 4px;
        }
        .form-table th {
            width: 240px;
        }
        .regular-text {
            width: 350px;
        }
    ');
}

// Settings page HTML
function wb_login_settings_page() {
    ?>
    <div class="wrap">
        <div class="wb-admin-header">
            <h1>🔐 WB OTP Login - Settings</h1>
            <p>Configure your OTP-based login system with MessageCentral integration</p>
        </div>
        
        <div class="wb-shortcode-box">
            <h3>📋 Shortcode Usage</h3>
            <div class="wb-shortcode-code" onclick="copyShortcode()">[wb_login]</div>
            <p style="margin-top: 10px;"><small>Copy this shortcode and paste it into any page or post to display the login form.</small></p>
        </div>
        
        <div class="wb-cred-help">
            <strong>💡 How to get MessageCentral Credentials:</strong><br>
            1. Login to your <a href="https://cpaas.messagecentral.com" target="_blank">MessageCentral CPaaS Dashboard</a><br>
            2. Go to Account Settings → API Credentials<br>
            3. Copy your Customer ID, Email, and generate Base64 API Key<br>
            4. Country Code: Use <code>IN</code> for India, <code>US</code> for USA, etc.<br>
            5. Dial Code: Use <code>91</code> for India, <code>1</code> for USA (without + sign)
        </div>
        
        <form method="post" action="options.php">
            <?php
            settings_fields('wb_login_settings');
            do_settings_sections('wb-otp-login');
            submit_button('💾 Save All Settings', 'primary', 'submit', true);
            ?>
        </form>
        
        <div style="margin-top: 30px; padding: 15px; background: #f0fdf4; border-left: 4px solid #22c55e; border-radius: 4px;">
            <strong>✅ Quick Setup Checklist:</strong><br>
            • Create a new page (e.g., "Login") and add shortcode <code>[wb_login]</code><br>
            • Enter your MessageCentral credentials above<br>
            • Customize colors, logo, and button styles<br>
            • Set your redirect URL (where users go after login)<br>
            • Save settings and test your login page!
        </div>
    </div>
    
    <script>
    function copyShortcode() {
        const shortcode = '[wb_login]';
        navigator.clipboard.writeText(shortcode);
        const box = document.querySelector('.wb-shortcode-code');
        const originalText = box.textContent;
        box.textContent = '✓ Copied!';
        setTimeout(() => {
            box.textContent = originalText;
        }, 2000);
    }
    </script>
    <?php
}

// ============================================
// DEFAULT SETTINGS ON ACTIVATION
// ============================================
function wb_login_activate() {
    $defaults = [
        'mc_customer_id' => 'C-CC324C927AF6570',
        'mc_email' => 'moc.liamgobfsctd@zyx',
        'mc_key' => 'Q2hhEfmlAMTIz',
        'mc_country' => 'IN',
        'mc_country_code' => '91',
        'logo_url' => '',
        'heading_text' => 'WELCOME BACK',
        'bg_color_1' => '#0f6c82',
        'bg_color_2' => '#0a3f5c',
        'card_bg' => '#f1f5f9',
        'heading_color' => '#1f2937',
        'btn_bg' => '#000000',
        'btn_text_color' => '#ffffff',
        'input_border' => '#d1d5db',
        'redirect_url' => '/dashboard/',
        'register_url' => '',
        'forgot_url' => '',
        'custom_css' => ''
    ];
    
    if (!get_option('wb_login_settings')) {
        add_option('wb_login_settings', $defaults);
    }
}
register_activation_hook(__FILE__, 'wb_login_activate');

While most SMS providers require complicated DLT registration processes, Message Central makes OTP integration much easier for developers and businesses.

In the next section, we’ll implement the complete WordPress OTP verification system using Message Central step-by-step with custom code integration.

Select your currency