[CSHARP] How To Login Zalo With Api Version 4

Xin chào mọi người, sau một hồi ngồi loay hoay xem cách để đăng nhập ứng dụng từ cách mạng xã hội như "FACEBOOK, GOOGLE,ZALO...v.v" thì mình tìm thấy bên trang laptrinhvb.net một bài viết mới cũng nói về cách đăng nhập trên.
Như mọi người dùng ở việt nam cũng đã biết zalo phát triển lên như một mạng xã hội đã từ lâu, và zalo cũng có nhiều thứ hay để mọi người phục vụ cho nhiều mục đích khác nhau.
 
Nhưng mình cảm thấy dùng zalo hiện tại bây giờ có nhiều thứ mà mạng xã hội này bắt người dùng mua bản Business Pro để có nhiều tính năng hơn, nhưng điều đó không ảnh hưởng gì đến việc mình hướng dẫn các bạn ở đây, đó là việc dùng mạng xã hội zalo để đăng nhập vào chương trình của mình hoàn toàn đơn giản.
Chúng ta bắt đầu nhé.

Đầ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}");
                }
            }
        }
    }
    
}

VIDEO DEMO:


Chúc các bạn thành công với thủ thuật trên.

DOWNLOAD SOURCE CODE

PASSWORD UNZIP: HUNG.PRO.VN

Đăng nhận xét

Mới hơn Cũ hơn