NEWS

[C#] Hướng dẫn đăng nhập zalo login sử dụng API v4 trên winform

[C#] Hướng dẫn đăng nhập zalo login sử dụng API v4 trên winform
Đăng bởi: Thảo Meo - Lượt xem: 2399 16:12:09, 11/06/2024C#   In bài viết

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.

ungdung_zalo_api

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!

DOWNLOAD SOURCE

THÔNG TIN TÁC GIẢ

BÀI VIẾT LIÊN QUAN

[C#] Hướng dẫn đăng nhập zalo login sử dụng API v4 trên winform
Đăng bởi: Thảo Meo - Lượt xem: 2399 16:12:09, 11/06/2024C#   In bài viết

CÁC BÀI CÙNG CHỦ ĐỀ

Đọc tiếp
.