Over time, One Time Password has become essential in building products that require users signing in and low-level user verification. Integrating this service is not only expensive but also might be difficult or unstable depending on the platform you decide to use.
They are various ways of achieving OTP service, but this writeup will be focusing on using WhatsApp and C#. The requirements for this exercise include
public class Message
{
public string Contact { get; set; }
public string Text { get; set; }
public bool IsDigit()
{
const string numbers = "0123456789";
var count = (from ch in Contact
where !numbers.Contains(ch)
select ch).Count();
var isNumber = (count == 0);
return isNumber;
}
}
public class WhatsAppMetadata
{
public static string MainPanel = "#pane-side";
public static string SearchField = "._2S1VP";
public static string UserChat = "#pane-side span[title=\"XXX\"]";
public static string UserName = "#main > span[title=\"XXX\"]";
public static string MessageInputField = "._2S1VP";
}
Go to your nugget package manager and install PuppeterSharp. This package is used to crawl the web using C# and chro4me
Add the following properties
This class have five important functions
private async Task InitBrowser()
{
Debug.WriteLine("Downloading. . .");
await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);
_browser = await Puppeteer.LaunchAsync(new LaunchOptions()
{
UserDataDir = Path.Combine(".", "user-data-dir"),
Headless = false
});
Debug.WriteLine("Browser downloaded. . .");
}
private async void InitWhatsApp()
{
var qrCodeAbsolutePath = _binPath.Replace("bin", "") + QrCodeImagePath;
_whatsAppPage = await _browser.NewPageAsync();
await _whatsAppPage.GoToAsync(WhatsAppUrl);
Try
{
await _whatsAppPage.WaitForSelectorAsync(WhatsAppMetadata.MainPanel);
}
catch (Exception)
{
Console.WriteLine("As a new User, you need to login");
await _whatsAppPage.ScreenshotAsync(qrCodeAbsolutePath);
Console.WriteLine($"send image in {qrCodeAbsolutePath} to your email && print to console");
await _whatsAppPage.WaitForSelectorAsync(WhatsAppMetadata.MainPanel);
}
await _whatsAppPage.ScreenshotAsync(qrCodeAbsolutePath);
}
private void SendMessages()
{
while (_messages.Any())
{
var message = _messages.Dequeue();
SendMessage(message);
}
}
private async void SendMessage(Message message)
{
if (message.IsDigit())
{
//load the new url and press send
var url = NewContactUrl.Replace("<PHONE>", message.Contact).Replace("<MESSAGE>",message.Text);
await _whatsAppPage.GoToAsync(url);
await _whatsAppPage.WaitForSelectorAsync(WhatsAppMetadata.MessageInputField);
await _whatsAppPage.Keyboard.PressAsync("Enter");
//Message Sent
Console.WriteLine("Message Sent");
return;
}
//Search complete
var searchInput = await _whatsAppPage.QuerySelectorAsync(WhatsAppMetadata.SearchField);
await searchInput.TypeAsync(message.Contact);
await _whatsAppPage.WaitForTimeoutAsync(500);
var fiendLocation = WhatsAppMetadata.UserChat.Replace("XXX", message.Contact);
var contactHandle = await _whatsAppPage.QuerySelectorAsync(fiendLocation);
await contactHandle.ClickAsync();
var messageSplit = message.Text.Split("\n");
foreach (var word in messageSplit)
{
await _whatsAppPage.Keyboard.DownAsync("Shift");
await _whatsAppPage.Keyboard.PressAsync("Enter");
await _whatsAppPage.Keyboard.UpAsync("Shift");
await _whatsAppPage.Keyboard.TypeAsync(word);
}
await _whatsAppPage.Keyboard.PressAsync("Enter");
}
public void AddMessage(Message message)
{
_messages.Enqueue(message);
if (_messages.Count == 1)
{
SendMessages();
}
}
var whatAppService = new WhatsAppService();
services.AddSingleton(whatAppService);
With all this done, you can go ahead and use the WhatAppService in your controllers to send Messages (including users One Time Password)
Leave a Reply