Integrate Login with Phone button on website


Introduction

Log in with Phone is a phone verification plugin that works on the frontend, similar to Sign in with Gmail/Facebook. It simplifies global phone number verification by using OTP/pass code. Log in with Phone eliminates the need for complex telecom registration and SMS API Gateway integration for each country.

To integrate the "Login with Phone" web plugin into your website, please follow the essential steps given below:

  1. 1. Get the Client ID
  2. 2. Integrate Login with Phone button on your web page

1. Get the Client Id

To configure the Log in with Phone button for your business, get the CLIENT_ID from the Profile Details section by signing into the Admin Dashboard at https://admin.phone.email. You will need to update the Client ID in the code snippet as instructed in step 2.

phone.email

2. Integrate Login with Phone button

The Log in with Phone integration page consists of two essential flows:

Display Log in button: This code displays the ‘Login with Phone’ button on your website.

Handle response: After the user’s phone number is verified, we return an access token on the redirect link (self webpage link). This code reads the access token from the query parameter and calls the eapi.phone.email/getuser API to get the verified mobile number.

Click here to see how Log in with Phone works on your website, try our hosted demo login page.

Quick integration: To integrate Log in with Phone quickly, follow these steps:

  • - Download the Log in with Phone page. Read the comments in the code snippet for technology-specific instructions.
  • - Place the Log in page(s) in your project development folder.
  • - Update the CLIENT_ID in the code.
  • - Load the Log in page hosted on your localhost/domain to test it.
  • - Note: You can also customize the user interface as per your need."

Note

  • CLIENT_ID: Populate value of CLIENT_ID variable with client id received in step 1.

<?php
/*
To test Sign-in with Phone functionaliy, please make following changes
    1. Please download Login.php file and paste it in your PHP app home directory.
    2. Manage routing and run this Login.php file.
*/
?>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <meta name="msapplication-TileColor" content="#0E0E0E">
    <meta name="template-color" content="#0E0E0E">
    <meta name="description" content="">
    <meta name="keywords" content="free SMS,OTP,phone email,free sms otp service">
    <meta name="author" content="">
    <title>New sign in</title>

    <style>
    .phem-container {
        display: flex;
        align-items: center;
        justify-content: center;
        margin: 50px 0;
    }

    .phem-input {
        padding: 12px 20px;
        display: inline-block;
        border: 1px solid #ccc;
        border-radius: 4px;
        box-sizing: border-box;
        margin-bottom: 20px;
    }

    .phem-card {
        color: #024430 !important;
        text-align: center;
        background-color: #fff;
        padding: 30px;
        border-radius: 0.5rem;
        box-shadow: 0 1px 3px rgba(17, 24, 39, .09);
        width: 100%;
        max-width: 420px;
        margin: 0 auto;
        font-family: sans-serif, serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
        line-height: 28px;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
    }
    </style>
</head>

<body style="background-color: #f1f5f9;">

    <?php
        /* Please replace XXXXXXXXXX with client id shown under profile section in admin dashboard (https://admin.phone.email) */
        $CLIENT_ID = 'XXXXXXXXXXXXXXXXXXX';
        $REDIRECT_URL = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https://" : "http://") . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
        $AUTH_URL = 'https://www.phone.email/auth/log-in?client_id='.$CLIENT_ID.'&redirect_url='.$REDIRECT_URL.'';
    ?>


    <?php
        if(!isset($_GET['access_token'])){
    ?>

    <!-- Display Login Button -->
    <div class="phem-container">
        <div class="phem-card">

            <img class="phe-login-img" width="250px" src="https://storage.googleapis.com/prod-phoneemail-prof-images/phem-widgets/phe-signin-box.svg"
                alt="phone email login demo">
            <h1 style="margin:10px; 0">Sign In</h1>
            <p style="color:#a6a6a6;">Welcome to Sign In with Phone  </p>

            <button
                style="display: flex; align-items: center; justify-content:center; padding: 14px 20px; background-color: #02BD7E; font-weight: bold; color: #ffffff; border: none; border-radius: 3px; font-size: inherit;cursor:pointer; max-width:320px; width:100%"
                id="btn_ph_login" name="btn_ph_login" type="button"
                onclick="window.open('<?php echo $AUTH_URL; ?>', 'peLoginWindow', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0, width=500, height=560, top=' + (screen.height - 600) / 2 + ', left=' + (screen.width - 500) / 2);">
                <img src="https://storage.googleapis.com/prod-phoneemail-prof-images/phem-widgets/phem-phone.svg"
                    alt="phone email" style="margin-right:10px;">
                Sign In with Phone
            </button>

        </div>
    </div>

    <?php } ?>


    <?php

    /* After successful phone number verification an access_token will be returned by auth verification popup. In this if condition  please use this access_token to call Phone Email API to get verified phone number.  */
    if(isset($_GET['access_token'])){

        /* To get verified phone number please call the getuser API */

        // Initialize cURL session
        $ch = curl_init();
        $url = "https://eapi.phone.email/getuser";
        $postData = array(
            'access_token' => $_GET['access_token'],
            'client_id' => $CLIENT_ID
        );

        // Set cURL options
        curl_setopt($ch, CURLOPT_URL, $url); // URL to submit the POST request
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Return the response as a string instead of outputting it directly
        curl_setopt($ch, CURLOPT_POST, true); // Set the request type to POST
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); // Set the POST data
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Ignore SSL certificate verification (not recommended in production)

        $response = curl_exec($ch);

        if ($response === false) {
            echo "cURL error: " . curl_error($ch);
            header('Location: /demo-login');
        }

        curl_close($ch);

        $json_data = json_decode($response,true);

        if($json_data['status'] != 200) {
            header('Location: /demo-login');
        }

        $country_code = $json_data['country_code'];
        $phone_no = $json_data['phone_no'];
        $ph_email_jwt = $json_data['ph_email_jwt'];
        setcookie('ph_email_jwt', $ph_email_jwt, time() + (86400 * 30), "/"); // 86400 = 1 day

        // Register User: If user corrosponding to this verified  mobile number does not exist in your user table then add the user in your user table and continue to the next step. If user already exists then skip the next step.

        // User Registration Form: Some websites require additional information about the user for first time log in. Hence as an optional step you can create user profile form here to capture additional details like First Name, Last Name, City etc and store them in your user table.

        // Send Email: We reccomend you to send welcome email to the user.
        //curl --location --request POST "https://api.phone.email/v1/sendmail" --ssl-no-revoke --header "Content-Type: application/json" --data-raw "{'apiKey':'API_KEY','fromCountryCode':'XXX','fromPhoneNo':'XXXXXXXXXX', 'toCountrycode':'XX','toPhoneNo':'XXXXXXXXXX','subject': 'Welcome to YOUR_BUSINESS_NAME','tinyFlag':true,'messageBody':'V2VsY29tZSB0byB5b3VyIEJVU0lORVNTX05BTUU='}"

        // Create Session: Store verified user phone number in session variable.

        // Redirect: Redirect user to the page of your choice as the user has successfully logged in.

        // Handle Logout (Optional): You can create logout button on your website as required.In the event of logout you must clear delete ph_email_jwt cookie and clear your session variables.  To delete cookie simply set it to blank -> setcookie("ph_email_jwt", "", time()-3600);
        ?>

    <div class="phem-container">
        <div class="phem-card">
            <img class="phe-login-img" width="250px" src="https://storage.googleapis.com/prod-phoneemail-prof-images/phem-widgets/phe-signin-success.svg"
                alt="phone email login demo">
            <div class="phem-card-body">
                <h1>Welcome!</h1>
                <h4 style="line-height:36px;">You are logged in successfully with <br />
                <?php echo $country_code.$phone_no;?></h4>

            </div>

            <button
                style="display: flex; align-items: center; justify-content:center; padding: 14px 20px; background-color: #02BD7E; font-weight: bold; color: #ffffff; border: none; border-radius: 3px; font-size: inherit;cursor:pointer; max-width:320px; width:100%"
                onclick="location.href='/demo-login'">Back</button>
        </div>
    </div>

    <?php
    } ?>

</body>

</html>

  

// Import necessary modules
const express = require("express");
const path = require("path");

// Create an instance of Express application
const app = express();

// Set the port for the server
const port = 3000;

// Serve static files from the 'public' directory
app.use(express.static(path.join(__dirname, "public")));

// Set the view engine and views directory
// app.set("view engine", "pug"); // Set Pug as the template engine
app.set("view engine", "ejs"); // Set EJS as the template engine
app.set("views", path.join(__dirname, "views"));

// Define a route for the home page
app.get("/", async function (req, res) {
  try {

    const CLIENT_ID = "YOUR_CLIENT_ID";
    const REDIRECT_URL = req.protocol + "://" + req.get("host") + req.originalUrl;
    const AUTH_URL = `https://www.phone.email/auth/log-in?client_id=${CLIENT_ID}&redirect_url=${REDIRECT_URL}`;

    // Extract the access token from the query parameters
    const accessToken = req.query.access_token;

    // Initialize user details and token flag
    const userDetails = { countryCode: "", phoneNo: "" };
    const hasToken = accessToken || false;

    // Prepare data for rendering the view
    const data = { hasToken, userDetails, authUrl: AUTH_URL };

    // If there's an access token, fetch user details
    if (hasToken) {
      const url = "https://eapi.phone.email/getuser";

      // Prepare the payload for the API request
      const payload = new FormData();
      payload.append("access_token", accessToken);
      payload.append("client_id", CLIENT_ID);

      // Make a POST request to the API
      const response = await fetch(url, { method: "POST", body: payload });
      const responseData = await response.json();

      // Populate user details with the API response
      userDetails.countryCode = responseData.country_code;
      userDetails.phoneNo = responseData.phone_no;
      userDetails.jwt = responseData.ph_email_jwt;
    }

    // Render the "index" view with the data
    res.render("index", data);
  } catch (error) {
    // Handle errors and provide a meaningful response
    console.error(error);
    return res.status(500).json({ message: "Internal server error." });
  }
});

// Start the server and listen on the specified port
app.listen(port, () => {
  console.log(`Server is running on port ${port}`);
});

For more details click on View on GitHub (Node JS) button


/* To test Sign-in with Phone  functionaliy, please make following changes
    1. Please download Login.js file and paste it in your ReactJS app home directory.
    2. Import Login.js component file in index.js
    3. Render Login component in index.js. */

import React, { useEffect, useState } from "react";

const App = () => {
  const searchParams = new URLSearchParams(window.location.search);
  const accessToken = searchParams.get('access_token');

  // Replace with your actual CLIENT_ID
  const CLIENT_ID = "YOUR_CLIENT_ID";

  const REDIRECT_URL = window.location.href;
  const AUTH_URL = `https://www.phone.email/auth/log-in?client_id=${CLIENT_ID}&redirect_url=${REDIRECT_URL}`;

  // Use state to manage user details
  const [userDetails, setUserDetails] = useState({
    countryCode: "",
    phoneNo: "",
    phEmailJwt: ""
  });

  const httpRequest = async () => {
    try {
      const url = "https://eapi.phone.email/getuser";
      const data = new FormData();

      data.append("access_token", accessToken);
      data.append("client_id", CLIENT_ID);

      const response = await fetch(url, { method: "POST", body: data });

      if (!response.ok) {
        throw new Error("Network response was not ok");
      }

      const responseData = await response.json();

      if (responseData.status !== 200) {
        throw new Error("Something went wrong");
      }

      const phEmailJwt = responseData.ph_email_jwt;

      setUserDetails({
        countryCode: responseData.country_code,
        phoneNo: responseData.phone_no,
        phEmailJwt: phEmailJwt
      });

      // Set cookie with 180-day expiration
      const cookieExpire = new Date(Date.now() + 180 * 24 * 60 * 60 * 1000).toUTCString();
      document.cookie = `ph_email_jwt=${phEmailJwt}; expires=${cookieExpire}; path=/`;

      // Register User: As the user phone number has been verified successfully. If user corrosponding to this verified  mobile number does not exist in your user table then register the user by creating a row in user table. If user already exists then simply continue to the next step.

      // Send Email: We reccomend you to send welcome email to the user.
      //curl --location --request POST "https://api.phone.email/v1/sendmail" --ssl-no-revoke --header "Content-Type: application/json" --data-raw "{'apiKey':'API_KEY','fromCountryCode':'XXX','fromPhoneNo':'XXXXXXXXXX', 'toCountrycode':'XX','toPhoneNo':'XXXXXXXXXX','subject': 'Welcome to YOUR_BUSINESS_NAME','tinyFlag':true,'messageBody':'V2VsY29tZSB0byB5b3VyIEJVU0lORVNTX05BTUU='}"

      // Create Session: Store verified user phone number in session variable.

      // Redirect: Redirect user to the page of your choice as the user has successfully logged in.

      // Handle Logout (Optional): You can create logout button on your website as required.In the event of logout you must clear delete ph_email_jwt cookie and clear your session variables.  To delete cookie simply set it to blank -> setcookie("ph_email_jwt", "", time()-3600);

    } catch (error) {
      console.error("Fetch error:", error);
    }
  };

  useEffect(() => {
    if (accessToken) {
      httpRequest();
    }
  }, [accessToken]);

  return (
    <React.Fragment>
      {!accessToken && (
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', margin: '50px 30px' }}>
          <div style={{ color: '#024430 !important', textAlign: 'center', backgroundColor: '#fff', padding: '30px', borderRadius: '0.5rem', boxShadow: '0 1px 3px rgba(17, 24, 39, .09)', width: '100%', maxWidth: '420px', margin: '0 auto', fontFamily: 'sans-serif, serif, system-ui, -apple-system, BlinkMacSystemFont, \'Segoe UI\', Roboto, Oxygen, Ubuntu, Cantarell, \'Open Sans\', \'Helvetica Neue\', sans-serif', lineHeight: '28px', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center' }}>
            <img className="phe-login-img" width="250px" src="https://storage.googleapis.com/prod-phoneemail-prof-images/phem-widgets/phe-signin-box.svg"
              alt="phone email login demo" />
            <h1 style={{ margin: "10px" }}>Sign In</h1>
            <p style={{ color: "#a6a6a6" }}>Welcome to Sign In with Phone</p>
            <button
              style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '14px 20px', backgroundColor: '#02BD7E', fontWeight: 'bold', color: '#ffffff', border: 'none', borderRadius: '3px', fontSize: 'inherit', cursor: 'pointer', maxWidth: '320px', width: '100%' }}
              id="btn_ph_login"
              name="btn_ph_login"
              type="button"
              onClick={() => window.open(AUTH_URL, 'peLoginWindow', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0, width=500, height=560, top=' + (window.screen.height - 600) / 2 + ', left=' + (window.screen.width - 500) / 2)}>
              <img src="https://storage.googleapis.com/prod-phoneemail-prof-images/phem-widgets/phem-phone.svg"
                alt="phone email" style={{ marginRight: "10px" }} />
              Sign In with Phone
            </button>
          </div>
        </div>
      )}

      {accessToken && (
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', margin: '50px 30px' }}>
          <div style={{ color: '#024430 !important', textAlign: 'center', backgroundColor: '#fff', padding: '30px', borderRadius: '0.5rem', boxShadow: '0 1px 3px rgba(17, 24, 39, .09)', width: '100%', maxWidth: '420px', margin: '0 auto', fontFamily: 'sans-serif, serif, system-ui, -apple-system, BlinkMacSystemFont, \'Segoe UI\', Roboto, Oxygen, Ubuntu, Cantarell, \'Open Sans\', \'Helvetica Neue\', sans-serif', lineHeight: '28px', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', }}>
            <img className="phe-login-img" width="250px" src="https://storage.googleapis.com/prod-phoneemail-prof-images/phem-widgets/phe-signin-success.svg" alt="phone email login demo" />
            <div className="phem-card-body">
              <h1>Welcome!</h1>
              <h4 style={{ lineHeight: "36px" }}>You are logged in successfully with <br />
                {userDetails.countryCode} {userDetails.phoneNo}
              </h4>
            </div>
            <button style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '14px 20px', backgroundColor: '#02BD7E', fontWeight: 'bold', color: '#ffffff', border: 'none', borderRadius: '3px', fontSize: 'inherit', cursor: 'pointer', maxWidth: '320px', width: '100%', }} onClick={() => window.location.href = '/'}>Back</button>
          </div>
        </div>
      )}
    </React.Fragment>
  );
};

export default App;



                                                    

For more details click on View on GitHub (React JS) button


/*************************** app.component.ts code  ***********************************/
import { Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Router, RouterOutlet } from '@angular/router';

import { ActivatedRoute } from '@angular/router';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule, RouterOutlet],
  templateUrl: './app.component.html',
})
export class AppComponent implements OnInit {
  accessToken: string = "";
  hasToken: boolean = false;
  errorMessage: string = "";
  CLIENT_ID: string = "13823986951097834119";
  userDetails = {
    countryCode: "",
    phoneNo: ""
  };

  constructor(private router: Router, private route: ActivatedRoute, private http: HttpClient) { }

  ngOnInit() {
    this.route.queryParams.subscribe(params => {
      this.accessToken = params['access_token'];
      if (this.accessToken) {
        this.hasToken = true;
        this.httpRequest();
      }
    });
  }

  httpRequest() {
    const url = "https://eapi.phone.email/getuser";
    const data = new FormData();

    data.append("access_token", this.accessToken);
    data.append("client_id", this.CLIENT_ID);

    this.http.post(url, data, { responseType: 'json' }).subscribe((response: any) => {
      this.userDetails = {
        countryCode: response.country_code,
        phoneNo: response.phone_no,
      };
    }, ({ message }: { message: string }) => { this.errorMessage = message });
  }

  openAuthWindow() {
    const REDIRECT_URL = window.location.href;
    const AUTH_URL = `https://www.phone.email/auth/log-in?client_id=${this.CLIENT_ID}&redirect_url=${REDIRECT_URL}`;
    window.open(AUTH_URL, 'peLoginWindow', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=560,top=' + (window.screen.height - 600) / 2 + ',left=' + (window.screen.width - 500) / 2);
  }

  handleBack() {
    this.accessToken = "";
    this.hasToken = false;
    this.router.navigate(['/']);
  }
}

/*************************** app.component.ts code end  ***********************************/


/*************************** app.component.html code start  ***********************************/

<style>
  .auth-container {
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 50px 30px;
  }

  .auth-box {
    color: #024430 !important;
    text-align: center;
    background-color: #fff;
    padding: 30px;
    border-radius: 0.5rem;
    box-shadow: 0 1px 3px rgba(17, 24, 39, .09);
    width: 100%;
    max-width: 420px;
    margin: 0 auto;
    font-family: sans-serif, serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
    line-height: 28px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
  }

  .auth-button {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 14px 20px;
    background-color: #02BD7E;
    font-weight: bold;
    color: #ffffff;
    border: none;
    border-radius: 3px;
    font-size: inherit;
    cursor: pointer;
    max-width: 320px;
    width: 100%;
  }
</style>

<main class="main">
  <div *ngIf="!hasToken" class="auth-container">
    <div class="auth-box">
      <img class="phe-login-img" width="250px"
        src="https://storage.googleapis.com/prod-phoneemail-prof-images/phem-widgets/phe-signin-box.svg"
        alt="phone email login demo" />
      <h1 style="margin: 10px;">Sign In</h1>
      <p style="color: #a6a6a6;">Welcome to Sign In with Phone</p>
      <button (click)="openAuthWindow()" class="auth-button">
        <img src="https://storage.googleapis.com/prod-phoneemail-prof-images/phem-widgets/phem-phone.svg"
          alt="phone email" style="margin-right: 10px;" />
        Sign In with Phone
      </button>
    </div>
  </div>

  <div *ngIf="hasToken">
    <div class="auth-container">
      <div class="auth-box">
        <img class="phe-login-img" width="250px"
          src="https://storage.googleapis.com/prod-phoneemail-prof-images/phem-widgets/phe-signin-success.svg"
          alt="phone email login demo" />
        <div class="phem-card-body">
          <h1>Welcome!</h1>
          <h4 style="line-height: 36px;">You are logged in successfully with <br /> {{ userDetails.countryCode }} {{
            userDetails.phoneNo }}</h4>
        </div>
        <button (click)="handleBack()" class="auth-button">Back</button>
      </div>
    </div>
  </div>

</main>
<router-outlet></router-outlet>

/*************************** app.component.html code end  ***********************************/


                                                    

For more details click on View on GitHub (Angular JS) button


  /*
    To test Sign-in with Phone functionaliy, please make following changes
    1. Please download page.js file and paste it in your Next JS app directory.
    2. Now try to run on your local machine.
  */

"use client";
import React, { useCallback, useEffect, useState, Suspense } from "react";
import { useSearchParams, useRouter } from "next/navigation";

function HomeContent() {
  const searchParams = useSearchParams();
  const router = useRouter();
  const accessToken = searchParams.get("access_token");

  // Replace with your actual CLIENT_ID
  const CLIENT_ID = "****************";

  // Use state to manage user details
  const [userDetails, setUserDetails] = useState({
    countryCode: "",
    phoneNo: "",
    phEmailJwt: "",
  });

  const httpRequest = async () => {
    try {
      const url = "https://eapi.phone.email/getuser";
      const data = new FormData();

      data.append("access_token", accessToken);
      data.append("client_id", CLIENT_ID);

      const response = await fetch(url, { method: "POST", body: data });

      if (!response.ok) {
        throw new Error("Network response was not ok");
      }

      const responseData = await response.json();

      if (responseData.status !== 200) {
        throw new Error("Something went wrong");
      }

      const phEmailJwt = responseData.ph_email_jwt;

      setUserDetails({
        countryCode: responseData.country_code,
        phoneNo: responseData.phone_no,
        phEmailJwt: phEmailJwt,
      });

      // Set cookie with 1-day expiration
      const cookieExpire = new Date(
        Date.now() + 1 * 24 * 60 * 60 * 1000
      ).toUTCString();
      document.cookie = `ph_email_jwt=${phEmailJwt}; expires=${cookieExpire}; path=/`;
    } catch (error) {
      console.error("Fetch error:", error);
    }
  };

  const openLoginWindow = useCallback(() => {
    const top = (window.screen.height - 600) / 2;
    const left = (window.screen.width - 500) / 2;

    const REDIRECT_URL = window.location.href;
    const AUTH_URL = `https://www.phone.email/auth/log-in?client_id=${CLIENT_ID}&redirect_url=${REDIRECT_URL}`;
    const APP_SETTING = `toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0, width=500, height=560, top=${top}, left=${left}`;

    window.open(AUTH_URL, "peLoginWindow", APP_SETTING);
  }, []);

  useEffect(() => {
    if (accessToken) {
      httpRequest();
    }
  }, [accessToken]);

  return (
    <React.Fragment>
      {!accessToken && (
        <div
          style={{
            display: "flex",
            alignItems: "center",
            justifyContent: "center",
            margin: "50px 30px",
          }}
        >
          <div
            style={{
              color: "#024430 !important",
              textAlign: "center",
              backgroundColor: "#fff",
              padding: "30px",
              borderRadius: "0.5rem",
              boxShadow: "0 1px 3px rgba(17, 24, 39, .09)",
              width: "100%",
              maxWidth: "420px",
              margin: "0 auto",
              fontFamily:
                "sans-serif, serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif",
              lineHeight: "28px",
              display: "flex",
              flexDirection: "column",
              alignItems: "center",
              justifyContent: "center",
            }}
          >
            <img
              className="phe-login-img"
              width="250px"
              src="https://storage.googleapis.com/prod-phoneemail-prof-images/phem-widgets/phe-signin-box.svg"
              alt="phone email login demo"
            />
            <h1 style={{ margin: "10px" }}>Sign In</h1>
            <p style={{ color: "#a6a6a6" }}>Welcome to Sign In with Phone</p>
            <button
              style={{
                display: "flex",
                alignItems: "center",
                justifyContent: "center",
                padding: "14px 20px",
                backgroundColor: "#02BD7E",
                fontWeight: "bold",
                color: "#ffffff",
                border: "none",
                borderRadius: "3px",
                fontSize: "inherit",
                cursor: "pointer",
                maxWidth: "320px",
                width: "100%",
              }}
              id="btn_ph_login"
              name="btn_ph_login"
              type="button"
              onClick={openLoginWindow}
            >
              <img
                src="https://storage.googleapis.com/prod-phoneemail-prof-images/phem-widgets/phem-phone.svg"
                alt="phone email"
                style={{ marginRight: "10px" }}
              />
              Sign In with Phone
            </button>
          </div>
        </div>
      )}

      {accessToken && (
        <div
          style={{
            display: "flex",
            alignItems: "center",
            justifyContent: "center",
            margin: "50px 30px",
          }}
        >
          <div
            style={{
              color: "#024430 !important",
              textAlign: "center",
              backgroundColor: "#fff",
              padding: "30px",
              borderRadius: "0.5rem",
              boxShadow: "0 1px 3px rgba(17, 24, 39, .09)",
              width: "100%",
              maxWidth: "420px",
              margin: "0 auto",
              fontFamily:
                "sans-serif, serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif",
              lineHeight: "28px",
              display: "flex",
              flexDirection: "column",
              alignItems: "center",
              justifyContent: "center",
            }}
          >
            <img
              className="phe-login-img"
              width="250px"
              src="https://storage.googleapis.com/prod-phoneemail-prof-images/phem-widgets/phe-signin-success.svg"
              alt="phone email login demo"
            />
            <div className="phem-card-body">
              <h1>Welcome!</h1>
              <h4 style={{ lineHeight: "36px" }}>
                You are logged in successfully with <br />
                {userDetails.countryCode} {userDetails.phoneNo}
              </h4>
            </div>
            <button
              style={{
                display: "flex",
                alignItems: "center",
                justifyContent: "center",
                padding: "14px 20px",
                backgroundColor: "#02BD7E",
                fontWeight: "bold",
                color: "#ffffff",
                border: "none",
                borderRadius: "3px",
                fontSize: "inherit",
                cursor: "pointer",
                maxWidth: "320px",
                width: "100%",
              }}
              onClick={() => {
                router.push("/");
              }}
            >
              Back
            </button>
          </div>
        </div>
      )}
    </React.Fragment>
  );
}

export default function Home() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <HomeContent />
    </Suspense>
  );
}


                                                    

For more details click on View on GitHub (Next JS) button


  /*
    To test Sign-in with Phone functionaliy, please make following changes
    1. Please download Login.vue file and paste it in your Vue JS project source(src) directory.
    2. Add import App from "./Login.vue"; in your main.js file.
    3. Now try to run on your local machine.
  */

<template>
  <div v-if="!accessToken" class="auth-container">
    <div class="auth-box">
      <img class="phe-login-img" width="250px"
        src="https://storage.googleapis.com/prod-phoneemail-prof-images/phem-widgets/phe-signin-box.svg"
        alt="phone email login demo" />
      <h1 style="margin: 10px;">Sign In</h1>
      <p style="color: #a6a6a6;">Welcome to Sign In with Phone</p>
      <button @click="openAuthWindow" class="auth-button">
        <img src="https://storage.googleapis.com/prod-phoneemail-prof-images/phem-widgets/phem-phone.svg"
          alt="phone email" style="margin-right: 10px;" />
        Sign In with Phone
      </button>
    </div>
  </div>

  <div v-else>
    <div class="auth-container">
      <div class="auth-box">
        <img class="phe-login-img" width="250px"
          src="https://storage.googleapis.com/prod-phoneemail-prof-images/phem-widgets/phe-signin-success.svg"
          alt="phone email login demo" />
        <div class="phem-card-body">
          <h1>Welcome!</h1>
          <h4 style="line-height: 36px;">You are logged in successfully with <br /> {{ userDetails.countryCode }} {{
            userDetails.phoneNo }}</h4>
        </div>
        <button @click="handleBack" class="auth-button">Back</button>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      accessToken: null,
      CLIENT_ID: "**************************",
      userDetails: {
        countryCode: "",
        phoneNo: "",
      },
    };
  },
  mounted() {
    const searchParams = new URLSearchParams(window.location.search);
    this.accessToken = searchParams.get('access_token');

    if (this.accessToken) {
      this.httpRequest();
    }
  },
  methods: {
    openAuthWindow() {
      const REDIRECT_URL = window.location.href;
      const AUTH_URL = `https://www.phone.email/auth/log-in?client_id=${this.CLIENT_ID}&redirect_url=${REDIRECT_URL}`;
      window.open(AUTH_URL, 'peLoginWindow', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=560,top=' + (window.screen.height - 600) / 2 + ',left=' + (window.screen.width - 500) / 2);
    },
    async httpRequest() {
      try {
        const url = "https://eapi.phone.email/getuser";
        const data = new FormData();

        data.append("access_token", this.accessToken);
        data.append("client_id", this.CLIENT_ID);

        const response = await fetch(url, { method: "POST", body: data });

        if (!response.ok) {
          throw new Error("Network response was not ok");
        }

        const responseData = await response.json();

        if (responseData.status !== 200) {
          throw new Error("Something went wrong");
        }

        this.userDetails = {
          countryCode: responseData.country_code,
          phoneNo: responseData.phone_no,
        };

        // Set cookie with 1-day expiration
        const cookieExpire = new Date(Date.now() + 1 * 24 * 60 * 60 * 1000).toUTCString();
        document.cookie = `ph_email_jwt=${responseData.ph_email_jwt}; expires=${cookieExpire}; path=/`;
      } catch (error) {
        console.error("Fetch error:", error);
      }
    },
    handleBack() { window.location.href = "/" },
  },
};
</script>

<style scoped>
body {
  background-color: #f1f5f9;
}

.auth-container {
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 50px 30px;
}

.auth-box {
  color: #024430 !important;
  text-align: center;
  background-color: #fff;
  padding: 30px;
  border-radius: 0.5rem;
  box-shadow: 0 1px 3px rgba(17, 24, 39, .09);
  width: 100%;
  max-width: 420px;
  margin: 0 auto;
  font-family: sans-serif, serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
  line-height: 28px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.auth-button {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 14px 20px;
  background-color: #02BD7E;
  font-weight: bold;
  color: #ffffff;
  border: none;
  border-radius: 3px;
  font-size: inherit;
  cursor: pointer;
  max-width: 320px;
  width: 100%;
}</style>


                                                    

For more details click on View on GitHub (Next JS) button


@RestController
@RequestMapping("/api")
public class PhoneVerificationController {

    private static final String CLIENT_ID = "your_client_id"; // Replace with your actual client ID
    private static final String PHONE_EMAIL_API_URL = "https://eapi.phone.email/getuser";

    @PostMapping("/get_verified_phone")
    public ResponseEntity<Map<String, Object>> getVerifiedPhone(@RequestBody Map<String, Object> requestPayload) {
        if (requestPayload.containsKey("access_token")) {
            String accessToken = requestPayload.get("access_token").toString();

            // Call the Phone Email API to get verified phone number
            RestTemplate restTemplate = new RestTemplate();
            Map<String, Object> data = new HashMap<>();
            data.put("access_token", accessToken);
            data.put("client_id", CLIENT_ID);

            try {
                Map<String, Object> response = restTemplate.postForObject(PHONE_EMAIL_API_URL, data, Map.class);

                if (response != null && response.containsKey("status") && response.get("status").equals(200)) {
                    Map<String, Object> responseBody = new HashMap<>();
                    responseBody.put("country_code", response.get("country_code"));
                    responseBody.put("phone_no", response.get("phone_no"));
                    responseBody.put("ph_email_jwt", response.get("ph_email_jwt"));

                    return ResponseEntity.ok(responseBody);
                } else {
                    return ResponseEntity.badRequest().body(Collections.singletonMap("error", "Invalid access token"));
                }
            } catch (Exception e) {
                return ResponseEntity.status(500).body(Collections.singletonMap("error", "Request failed: " + e.getMessage()));
            }
        }
        return ResponseEntity.badRequest().body(Collections.singletonMap("error", "Access token not provided"));
    }
}


from django.shortcuts import render
from django.http import JsonResponse
import requests

def index(request):
    try:

        # Phone.email API credentials
        CLIENT_ID = "YOUR_CLIENT_ID"
        REDIRECT_URL = request.scheme + '://' + request.get_host()
        AUTH_URL = f"https://www.phone.email/auth/log-in?client_id={CLIENT_ID}&redirect_url={REDIRECT_URL}"

        # Retrieve access_token from the query parameters
        access_token = request.GET.get('access_token', None)

        # Initialize user_details dictionary
        user_details = {'countryCode': '', 'phoneNo': '', 'jwt': ''}

        # Check if access_token is present
        has_token = access_token is not None

        # Data dictionary to be passed to the template
        data = {'hasToken': has_token, 'userDetails': user_details, 'authUrl': AUTH_URL}

        if has_token:
            # Fetch user details using the Phone.email API
            url = "https://eapi.phone.email/getuser"
            payload = {'access_token': access_token, 'client_id': CLIENT_ID}

            # Make a POST request to the Phone.email API
            response = requests.post(url, data=payload)

            # Parse the JSON response
            response_data = response.json()

            # Update user_details with fetched data
            user_details['countryCode'] = response_data['country_code']
            user_details['phoneNo'] = response_data['phone_no']
            user_details['jwt'] = response_data['ph_email_jwt']

        # Render the 'index.html' template with the data
        response = render(request, 'index.html', data)

        # Set the Cross-Origin-Opener-Policy header for handling popups
        response['Cross-Origin-Opener-Policy'] = 'same-origin-allow-popups'

        return response

    except Exception as error:
        # Return a JSON response for internal server error
        return JsonResponse({'message': 'Internal server error.'}, status=500)

Once you've completed these steps, you'll begin to notice a "Login with Phone" button appearing on your webpage.

Should you encounter any technical challenges during the integration process, please don't hesitate to reach out to us for assistance.