- [C#] Chia sẻ source code tạo mã QR MOMO đa năng Winform
- [C#] Chia sẻ source code phần mềm lên lịch tự động chạy ứng dụng Scheduler Task Winform
- [Phần mềm] Tải và cài đặt phần mềm Sublime Text 4180 full version
- [C#] Hướng dẫn download file từ Minio Server Winform
- [C#] Hướng dẫn đăng nhập zalo login sử dụng API v4 trên winform
- [SOFTWARE] Phần mềm gởi tin nhắn Zalo Marketing Pro giá rẻ mềm nhất thị trường
- [C#] Việt hóa Text Button trên MessageBox Dialog Winform
- [DEVEXPRESS] Chia sẻ code các tạo report in nhiều hóa đơn trên XtraReport C#
- [POWER AUTOMATE] Hướng dẫn gởi tin nhắn zalo từ file Excel - No code
- [C#] Chia sẻ code lock và unlock user trong domain Window
- [DEVEXPRESS] Vẽ Biểu Đồ Stock Chứng Khoán - Công Cụ Thiết Yếu Cho Nhà Đầu Tư trên Winform
- [C#] Hướng dẫn bảo mật ứng dụng 2FA (Multi-factor Authentication) trên Winform
- [C#] Hướng dẫn convert HTML code sang PDF File trên NetCore 7 Winform
- [C#] Hướng dẫn viết ứng dụng chat với Gemini AI Google Winform
- Hướng dẫn khóa file bằng nhiều process id, không cho xóa tập tin
- Hướng dẫn cách tạo Product Id cho ứng dụng phần mềm XXXXX-XXXXX-XXXXX-XXXXX
- [SQLSERVER] Hướng dẫn tạo script sql từ ứng dụng Sqlserver management Studio
- [C#] Hướng dẫn sử dụng thư viện AutoITx lấy id và password Ultraviewer trên winform
- [VB.NET] Hướng dẫn lấy thông tin tài khoản đăng nhập windows và khởi động lại ứng dụng ở chế độ Administrator
- [C#] Sử dụng thư viện Polly gửi lại request api khi request bị lỗi hay rớt mạng
[C#] Hướng dẫn đăng nhập zalo login sử dụng API v4 trên winform
Xin chào các bạn, bài viết hôm nay mình chia sẻ các bạn source code cách đăng nhập vào ứng dụng zalo sử dụng API version 4.
[C#] How to login zalo with api version 4
Video Demo ứng dụng login with zalo:
Đầu tiên, các bạn cần đăng nhập vào Zalo Developer để tạo 1 ứng dụng.
Như ở hình mình có tạo 1 ứng dụng với tên LoginDemoApp,
Khi các bạn tạo xong, lấy thông tin ID, khóa bí mật và kích hoạt ứng dụng sang trạng thái đang hoạt động.
Full source code C# login:
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Security.Policy;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Windows.Automation;
using System.Windows.Forms;
using UIAutomationClient;
using TreeScope = UIAutomationClient.TreeScope;
namespace LoginZaloDemo
{
public partial class Form1 : Form
{
private const string ClientId = "xxxx";
private const string ClientSecret = "xxxxx";
private const string RedirectUri = "https://laptrinhvb.net";
private string codeVerifier;
private string state;
private readonly CUIAutomation _automation;
public string url = "";
[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
private void BringToTop()
{
IntPtr hWnd = this.Handle; // Get the window handle of the form
SetForegroundWindow(hWnd); // Bring the form to the topmost screen
}
public class FocusChangeHandler : IUIAutomationFocusChangedEventHandler
{
private readonly Form1 _listener;
public FocusChangeHandler(Form1 listener)
{
_listener = listener;
}
public void HandleFocusChangedEvent(IUIAutomationElement element)
{
if (element != null)
{
try
{
// Lấy ID của tiến trình hiện tại
int processId = element.CurrentProcessId;
// Lấy tiến trình hiện tại
Process process = Process.GetProcessById(processId);
// Kiểm tra xem tiến trình này có phải là Chrome không
if (IsChromeProcess(process))
{
try
{
IUIAutomationElement elm = this._listener._automation.ElementFromHandle(process.MainWindowHandle);
IUIAutomationCondition Cond = this._listener._automation.CreatePropertyCondition(30003, 50004);
IUIAutomationElementArray elm2 = elm.FindAll(TreeScope.TreeScope_Descendants, Cond);
bool urlFound = false;
// Chuyển đổi elm2 thành danh sách có thể lặp qua
List<IUIAutomationElement> elements = new List<IUIAutomationElement>();
for (int i = 0; i < elm2.Length; i++)
{
elements.Add(elm2.GetElement(i));
}
foreach (IUIAutomationElement elm3 in elements)
{
IUIAutomationValuePattern val = (IUIAutomationValuePattern)elm3.GetCurrentPattern(10002);
if (val != null && val.CurrentValue != "")
{
if (val.CurrentValue.Contains("?code="))
{
this._listener.url = val.CurrentValue;
Debug.WriteLine("Process will be killed due to URL: " + val.CurrentValue);
CloseChromeTab(process.MainWindowHandle);
break;
}
Debug.WriteLine("URL found: " + val.CurrentValue);
}
}
}
catch (Exception ex)
{
Debug.WriteLine("Inner Exception: " + ex.Message);
Debug.WriteLine("Stack Trace: " + ex.StackTrace);
}
}
}
catch (Exception ex)
{
Debug.WriteLine("Outer Exception: " + ex.Message);
Debug.WriteLine("Stack Trace: " + ex.StackTrace);
}
}
}
// Phương thức kiểm tra xem tiến trình có phải là Chrome không
private bool IsChromeProcess(Process process)
{
return process != null && process.ProcessName.ToLower().Contains("chrome");
}
private void CloseChromeTab(IntPtr chromeMainWindowHandle)
{
// Gửi tin nhắn WM_CLOSE để đóng cửa sổ Chrome
Win32.PostMessage(chromeMainWindowHandle, Win32.WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
}
public static class Win32
{
// Khai báo hằng số và phương thức từ User32.dll
public const int WM_CLOSE = 0x0010;
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
}
}
public Form1()
{
InitializeComponent();
GenerateCodeVerifierAndState();
_automation = new CUIAutomation();
_automation.AddFocusChangedEventHandler(null, new FocusChangeHandler(this));
}
private void GenerateCodeVerifierAndState()
{
codeVerifier = GenerateRandomString(43, true);
state = GenerateRandomString(32, false);
}
private string GenerateRandomString(int length, bool mixedCase)
{
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
var random = new Random();
var builder = new StringBuilder(length);
for (int i = 0; i < length; i++)
{
char c = chars[random.Next(chars.Length)];
if (mixedCase && i % 2 == 0)
{
c = char.ToUpper(c);
}
builder.Append(c);
}
return builder.ToString();
}
private string Base64UrlEncode(byte[] input)
{
var output = Convert.ToBase64String(input)
.Replace('+', '-')
.Replace('/', '_')
.TrimEnd('=');
return output;
}
public string GetCodeFromUrl(string url)
{
if (string.IsNullOrEmpty(url))
return string.Empty;
try
{
var uri = new Uri(url);
var queryParams = HttpUtility.ParseQueryString(uri.Query);
return queryParams.Get("code") ?? string.Empty;
}
catch (Exception)
{
return string.Empty;
}
}
public static async Task WaitUntilAsync(Func<bool> condition, int timeoutMilliseconds = Timeout.Infinite, int sleepMilliseconds = 100)
{
int elapsed = 0;
while (!condition() && elapsed < timeoutMilliseconds)
{
await Task.Delay(sleepMilliseconds);
elapsed += sleepMilliseconds;
}
if (elapsed >= timeoutMilliseconds)
{
throw new TimeoutException($"Condition not met within {timeoutMilliseconds} milliseconds.");
}
}
public static string FindBrowserPath()
{
// Các đường dẫn của Chrome
string[] chromePaths = new string[] { @"C:\Program Files\Google\Chrome\Application\chrome.exe", @"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" };// Trên32 và 64-bit Windows
// Các đường dẫn của Microsoft Edge
string[] edgePaths = new string[] { @"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe", @"C:\Program Files\Microsoft\Edge\Application\msedge.exe" };// Trên32 và 64-bit Windows
// Thêm các đường dẫn của Microsoft Edge vào danh sách
string[] possiblePaths = chromePaths.Concat(edgePaths).ToArray();
foreach (string path in possiblePaths)
{
if (File.Exists(path))
{
return path;
}
}
// Nếu không tìm thấy, trả về null
return null;
}
private async void btnLogin_Click(object sender, EventArgs e)
{
try
{
// Step 1: Get an authorization code
using (var sha256 = SHA256.Create())
{
url = string.Empty;
byte[] codeVerifierBytes = Encoding.ASCII.GetBytes(codeVerifier);
byte[] codeVerifierHash = sha256.ComputeHash(codeVerifierBytes);
string codeChallenge = Base64UrlEncode(codeVerifierHash);
string authorizationUrl = $"https://oauth.zaloapp.com/v4/permission?app_id={ClientId}&redirect_uri={RedirectUri}&code_challenge={codeChallenge}&code_challenge_method=S256&state={state}";
//System.Diagnostics.Process.Start(authorizationUrl);
string chromePath = FindBrowserPath();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = chromePath;
startInfo.Arguments = $"--incognito --disable-notifications {authorizationUrl}"; // Mở Chrome ở chế độ ẩn danh và tắt cảnh báo
Process process = Process.Start(startInfo);
process.WaitForInputIdle(); // Chờ Chrome sẵn sàng
}
await WaitUntilAsync(() => !string.IsNullOrEmpty(url), 120000);
string accessToken = "";
string Url = "https://" + url;
var authorizationCode = GetCodeFromUrl(Url);
string tokenUrl = "https://oauth.zaloapp.com/v4/access_token";
var tokenRequest = new HttpRequestMessage(HttpMethod.Post, tokenUrl);
tokenRequest.Headers.Add("secret_key", ClientSecret);
tokenRequest.Content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("app_id", ClientId),
new KeyValuePair<string, string>("code", authorizationCode),
new KeyValuePair<string, string>("grant_type", "authorization_code"),
new KeyValuePair<string, string>("code_verifier", codeVerifier),
});
using (var client = new HttpClient())
{
var tokenResponse = await client.SendAsync(tokenRequest);
var tokenContent = await tokenResponse.Content.ReadAsStringAsync();
if (tokenResponse.IsSuccessStatusCode)
{
//var tokenData = JsonConvert.DeserializeObject<dynamic>(tokenContent);
//accessToken = tokenData.access_token;
JObject tokenData = JsonConvert.DeserializeObject<JObject>(tokenContent);
// Kiểm tra xem "access_token" có tồn tại trong đối tượng JSON không
if (tokenData["access_token"] != null)
{
accessToken = tokenData["access_token"].ToString();
}
else
{
MessageBox.Show("Access token not found in the response.");
}
}
else
{
MessageBox.Show($"Error: {tokenContent}");
}
}
GetUserInfo(accessToken);
}
catch (Exception ex)
{
MessageBox.Show($"Error: {ex.Message}");
}
}
private async void GetUserInfo(string accessToken)
{
string userInfoUrl = "https://graph.zalo.me/v2.0/me?fields=id,name,picture,phone";
var userInfoRequest = new HttpRequestMessage(HttpMethod.Get, userInfoUrl);
userInfoRequest.Headers.Add("access_token", accessToken);
using (var client = new HttpClient())
{
var userInfoResponse = await client.SendAsync(userInfoRequest);
var userInfoContent = await userInfoResponse.Content.ReadAsStringAsync();
if (userInfoResponse.IsSuccessStatusCode)
{
JObject userInfo = JsonConvert.DeserializeObject<JObject>(userInfoContent);
if (userInfo["error"].ToString() == "100")
{
return;
}
string userId = userInfo["id"].ToString();
string userName = userInfo["name"].ToString();
string phone = userInfo["phone"] != null ? userInfo["phone"].ToString() : "N/A";
string userPictureUrl = userInfo["picture"]?["data"]?["url"].ToString();
BringToTop();
//MessageBox.Show($"User ID: {userId}\nName: {userName}\nPicture URL: {userPictureUrl}");
lblID.Text = userId;
lblUsername.Text = userName;
pictureBox1.LoadAsync(userPictureUrl);
}
else
{
MessageBox.Show($"Error: {userInfoContent}");
}
}
}
}
}
Thanks for watching!