public ActionResult LineCallback(string code, string state)
        {
            if (state == Properties.Settings.Default.Line_State_code)
            {
                #region Api變數宣告
                WebClient wc = new WebClient();
                wc.Encoding = Encoding.UTF8;
                wc.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
                string result           = string.Empty;
                NameValueCollection nvc = new NameValueCollection();
                #endregion
                try
                {
                    //取回Token
                    string ApiUrl_Token = "https://api.line.me/oauth2/v2.1/token";
                    nvc.Add("grant_type", "authorization_code");
                    nvc.Add("code", code);
                    nvc.Add("redirect_uri", "http://localhost:61177" + Url.Action("LineCallback", "Login"));
                    nvc.Add("client_id", Properties.Settings.Default.Line_Channel_ID);
                    nvc.Add("client_secret", Properties.Settings.Default.Line_Channel_Secret);
                    string         JsonStr  = Encoding.UTF8.GetString(wc.UploadValues(ApiUrl_Token, "POST", nvc));
                    LineLoginToken ToKenObj = JsonConvert.DeserializeObject <LineLoginToken>(JsonStr);
                    wc.Headers.Clear();

                    //取回User Profile
                    string ApiUrl_Profile = "https://api.line.me/v2/profile";
                    wc.Headers.Add("Authorization", "Bearer " + ToKenObj.access_token);
                    string      UserProfile = wc.DownloadString(ApiUrl_Profile);
                    LineProfile ProfileObj  = JsonConvert.DeserializeObject <LineProfile>(UserProfile);

                    //return RedirectToAction("UserProfile", "Login", new { displayName = ProfileObj.displayName, pictureUrl = ProfileObj.pictureUrl });
                    ViewBag.DisplayName = ProfileObj.displayName;
                    ViewBag.PictureUrl  = ProfileObj.pictureUrl;
                    return(View());
                }
                catch (Exception ex)
                {
                    string msg = ex.Message;
                    throw;
                }
            }
            return(View());
        }
        public ActionResult AfterLineLogin(string state, string code, string error, string error_description)
        {
            if (!string.IsNullOrEmpty(error))
            {//用戶沒授權你的LineApp
                ViewBag.error             = error;
                ViewBag.error_description = error_description;
                return(View());
            }

            if (TempData["state"] == null)
            {//可能使用者停留Line登入頁面太久
                return(Content("頁面逾期"));
            }

            if (Convert.ToString(TempData["state"]) != state)
            {//使用者原先Request QueryString的TempData["state"]和Line導頁回來夾帶的state Querystring不一樣,可能是parameter tampering或CSRF攻擊
                return(Content("state驗證失敗"));
            }

            if (Convert.ToString(TempData["state"]) == state)
            {//state字串驗證通過
                //取得id_token和access_token:https://developers.line.biz/en/docs/line-login/web/integrate-line-login/#spy-getting-an-access-token
                string         issue_token_url = "https://api.line.me/oauth2/v2.1/token";
                HttpWebRequest request         = (HttpWebRequest)WebRequest.Create(issue_token_url);
                request.Method      = "POST";
                request.ContentType = "application/x-www-form-urlencoded";
                //必須透過ParseQueryString()來建立NameValueCollection物件,之後.ToString()才能轉換成queryString
                NameValueCollection postParams = HttpUtility.ParseQueryString(string.Empty);
                postParams.Add("grant_type", "authorization_code");
                postParams.Add("code", code);
                postParams.Add("redirect_uri", "https://localhost:44384/Home/AfterLineLogin");
                postParams.Add("client_id", "1654660526");
                postParams.Add("client_secret", "7c82a8d2dd3c0fa465e66ae90abaeac6");
                string para = postParams.ToString();

                //要發送的字串轉為byte[]
                byte[] byteArray = Encoding.UTF8.GetBytes(postParams.ToString());
                using (Stream reqStream = request.GetRequestStream())
                {
                    reqStream.Write(byteArray, 0, byteArray.Length);
                }//end using

                //API回傳的字串
                string responseStr = "";
                //發出Request
                try
                {
                    using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                    {
                        using (StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
                        {
                            responseStr = sr.ReadToEnd();
                        }//end using
                    }
                }
                catch (Exception ex)
                {
                    return(Content(ex.ToString()));
                }

                LineLoginToken tokenObj = JsonConvert.DeserializeObject <LineLoginToken>(responseStr);
                string         id_token = tokenObj.id_token;

                //方案總管>參考>右鍵>管理Nuget套件 搜尋 System.IdentityModel.Tokens.Jwt 來安裝
                var             jst  = new System.IdentityModel.Tokens.Jwt.JwtSecurityToken(id_token);
                LineUserProfile user = new LineUserProfile();
                //↓自行決定要從id_token的Payload中抓什麼user資料
                user.userId      = jst.Payload.Sub;
                user.displayName = jst.Payload["name"].ToString();
                user.pictureUrl  = jst.Payload["picture"].ToString();
                if (jst.Payload.ContainsKey("email") && !string.IsNullOrEmpty(Convert.ToString(jst.Payload["email"])))
                {//有包含email,使用者有授權email個資存取,並且用戶的email有值
                    user.email = jst.Payload["email"].ToString();
                }


                string access_token = tokenObj.access_token;
                ViewBag.access_token = access_token;
                #region 接下來是為了抓用戶的statusMessage狀態消息,如果你不想要可以省略不發出下面的Request

                //Social API v2.1 Getting user profiles
                //https://developers.line.biz/en/docs/social-api/getting-user-profiles/
                //取回User Profile
                string profile_url = "https://api.line.me/v2/profile";


                HttpWebRequest req = (HttpWebRequest)WebRequest.Create(profile_url);
                req.Headers.Add("Authorization", "Bearer " + access_token);
                req.Method = "GET";
                //API回傳的字串
                string resStr = "";
                //發出Request
                using (HttpWebResponse res = (HttpWebResponse)req.GetResponse())
                {
                    using (StreamReader sr = new StreamReader(res.GetResponseStream(), Encoding.UTF8))
                    {
                        resStr = sr.ReadToEnd();
                    }//end using
                }



                LineUserProfile userProfile = JsonConvert.DeserializeObject <LineUserProfile>(resStr);
                user.statusMessage = userProfile.statusMessage;//補上狀態訊息

                #endregion

                //ViewBag.user = JsonConvert.SerializeObject(user, new JsonSerializerSettings
                //{
                //    ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
                //    Formatting = Formatting.Indented
                //});

                var member = db.member
                             .Where(b => b.line_id == user.userId)
                             .FirstOrDefault();
                if (member == null)
                {
                    return(RedirectToAction("line_register", "Home", user));
                }
                if ((member != null))
                {
                    TempData["message"] = "login success !";
                    Session["username"] = member.name;

                    Session["member_id"] = member.id;
                    Session["level"]     = member.level;
                    Response.Redirect("member");
                }
            }//end if

            return(View());
        }
        public OperationResult GetLineInfo(string code)
        {
            var or = new OperationResult();

            try
            {
                var            url     = "https://api.line.me/oauth2/v2.1/token";
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);

                request.Method      = "POST";
                request.ContentType = "application/x-www-form-urlencoded";
                NameValueCollection postParams = HttpUtility.ParseQueryString(string.Empty);

                var values = new Dictionary <string, string> {
                    { "grant_type", "authorization_code" },
                    { "client_id", $"{WebConfigurationManager.AppSettings["Line_client_id"]}" },
                    { "client_secret", $"{WebConfigurationManager.AppSettings["Line_client_secret"]}" },
                    { "code", code },
                    { "redirect_uri", $"{WebConfigurationManager.AppSettings["WebsiteUrl"]}/Account/LineLogin" }
                };
                foreach (var kvp in values)
                {
                    postParams.Add(kvp.Key, kvp.Value);
                }

                byte[] byteArray = Encoding.UTF8.GetBytes(postParams.ToString());
                using (Stream reqStream = request.GetRequestStream())
                {
                    reqStream.Write(byteArray, 0, byteArray.Length);
                }

                string responseStr = "";

                using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                {
                    using (StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
                    {
                        responseStr = sr.ReadToEnd();
                    }
                }

                LineLoginToken tokenObj = JsonConvert.DeserializeObject <LineLoginToken>(responseStr);
                string         id_token = tokenObj.Id_token;

                var             jst  = new System.IdentityModel.Tokens.Jwt.JwtSecurityToken(id_token);
                LineUserProfile user = new LineUserProfile();
                user.UserId      = jst.Payload.Sub;
                user.DisplayName = jst.Payload["name"].ToString();
                user.PictureUrl  = jst.Payload["picture"].ToString();
                if (jst.Payload.ContainsKey("email") && !string.IsNullOrEmpty(Convert.ToString(jst.Payload["email"])))
                {
                    user.Email = jst.Payload["email"].ToString();
                }

                or.IsSuccessful = true;
                or.MessageInfo  = JsonConvert.SerializeObject(user);
            }
            catch (Exception ex)
            {
                or.IsSuccessful = false;
                or.Exception    = ex;
                or.MessageInfo  = "發生錯誤";
            }
            return(or);
        }