欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

netCore3.0实现微信扫码登录

程序员文章站 2023-12-28 14:25:28
...


一、总体流程

第1步:请求code(前端)
第2步:前端通过获取的code请求API获取access_token(第2步之后都是后台API写代码)
第3步:API通过access_token调用接口
第4步:获取用户个人信息(UnionID机制)

二、代码

1.Index.html

<span>登录2 <a id="img2"><img src="~/images/icon48_wx_logo.png" /></a></span>

$('#img2').click(function (e) {
            var postSubmit = $.ajax({
                type: "GET",
                contentType: "application/json",
                url: "Index?handler=LoginIn",
                //data: { code: code },
               success: function (data) {
                    if (status == 200)
                    {
                        alert("成功");
                        //写自己的登录业务
                    }
                },
                error: function (jqXHR) {
                    alert("发生错误:" + jqXHR.status);
                }
            }).done(function (response) {
                alert(response);
            });
        });

2.Index.html.cs

public void OnGetLoginIn() 
        {
            try
            {
                Random random = new Random(Environment.TickCount);
                string state = random.Next(100000,999999).ToString();
                //string tokenUri = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=wxf1f84ee1c835dc1e&secret=a0b7f9516303199ea3fe3b39f7a930b0&code=0110XdHa1yrN4A0gojHa1kJ4ww40XdHe&state=state&grant_type=authorization_code";
                string tokenUri = WeChatDefaults.AccessTokenEndpoint
                    + "?appid=" + WeChatDefaults.AppId
                    + "&secret=" + WeChatDefaults.AppSecret
                    + "&code=" + "0010wz0w3C0mrV2nT14w3XzjVp20wz0a" //code为前端传入参数,自行获取,目前是写死的
                    + "&state=" + state
                    + "&grant_type=authorization_code";

                string resultAccessToken = ClientRequest(tokenUri, string.Empty, "POST");
                if (!string.IsNullOrEmpty(resultAccessToken))
                {
                    WeChatTocken weChatTocken1 = new WeChatTocken();
                    weChatTocken1 = JsonConvert.DeserializeObject<WeChatTocken>(resultAccessToken);
                    if (!string.IsNullOrEmpty(weChatTocken1.Access_Token))
                    {
                        string userUri = WeChatDefaults.UserInformationEndpoint 
                            + "?access_token=" 
                            + weChatTocken1.Access_Token 
                            + "&openid=" + weChatTocken1.OpenId;

                        string resultUserInfo = ClientRequest(userUri, string.Empty, "POST");
                        if (!string.IsNullOrEmpty(resultUserInfo))
                        {
                            WeChatUserInfo weChatUserInfo1 = new WeChatUserInfo();
                            weChatUserInfo1 = JsonConvert.DeserializeObject<WeChatUserInfo>(resultUserInfo);
                            if (!string.IsNullOrEmpty(weChatUserInfo1.OpenId))
                            {
                                Console.WriteLine("成功:" + weChatUserInfo1.OpenId);
                            }
                            else
                            {
                                Console.WriteLine("失败:" + weChatUserInfo1.OpenId);
                            }                            
                        }
                        else 
                        {
                            _logger.LogInformation("请求微信用户基本信息失败");
                        }
                    }
                    else
                    {
                        _logger.LogInformation("请求access_token失败");
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }            
        }
        
		/// <summary>
        /// 发送请求(get/post/http/https)
        /// </summary>
        /// <param name="uri">请求地址</param>
        /// <param name="JsonStr">json数据</param>
        /// <param name="Method">请求方式POST/GET</param>
        /// <returns></returns>
        public string ClientRequest(string uri, string JsonStr, string Method = "POST")
        {
            try
            {
                var httpRequest = (HttpWebRequest)HttpWebRequest.Create(uri);
                httpRequest.Method = Method;
                httpRequest.ContentType = "application/json";
                if (Method.ToLower() == "get")
                {
                    httpRequest.ContentType = "application/x-www-form-urlencoded";
                }
                httpRequest.Proxy = null;
                httpRequest.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13";
                httpRequest.Headers.Add("Accept-Language", "zh-cn,en-us;q=0.8,zh-hk;q=0.6,ja;q=0.4,zh;q=0.2");
                httpRequest.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";

                //如果是发送HTTPS请求  
                if (uri.StartsWith("https", StringComparison.OrdinalIgnoreCase))
                {
                    ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
                    httpRequest.ProtocolVersion = HttpVersion.Version10;
                    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
                }
                else
                {
                    ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
                    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
                }

                if (!string.IsNullOrEmpty(JsonStr))
                {
                    using (var dataStream = new StreamWriter(httpRequest.GetRequestStream()))
                    {
                        dataStream.Write(JsonStr);
                        dataStream.Flush();
                        dataStream.Close();
                    }
                }

                var httpResponse = (HttpWebResponse)httpRequest.GetResponse();
                using (var dataStream = new StreamReader(httpResponse.GetResponseStream()))
                {
                    var result = dataStream.ReadToEnd();
                    return result;
                }
            }
            catch (Exception ex)
            {
                return "{\"error\":\"" + ex.Message + "\"}";
            }
        }

3.WeChatHelper.cs

public class WeChatHelper
    {
        public WeChatHelper()
        {
        }

        /// <summary>
        /// 根据AppID和AppSecret获得access token(默认过期时间为2小时)
        /// </summary>
        /// <returns>Dictionary</returns>
        public static Dictionary<string, object> GetAccessToken()
        {
            //获得配置信息
            //oauth_config config = oauth_helper.get_config(2);
            string send_url = WeChatDefaults.AccessTokenEndpoint 
                + "?appid=" + WeChatDefaults.AppId 
                + "&secret=" + WeChatDefaults.AppSecret 
                + "&code=CODE&grant_type=authorization_code";
            //发送并接受返回值
            using (HttpClient client = new HttpClient()) 
            {
                var result = client.GetStringAsync(send_url);
                if (string.IsNullOrEmpty(result.Result) && (result.Result.Contains("errmsg") || result.Result.Contains("errmsg")))
                {
                    return null;
                }
                try
                {
                    Dictionary<string, object> dic = JsonConvert.DeserializeObject<Dictionary<string, object>>(result.Result);
                    return dic;
                }
                catch
                {
                    return null;
                }
            }
        }

        /// <summary>
        /// 取得临时的Access Token(默认过期时间为2小时)
        /// </summary>
        /// <param name="code">临时Authorization Code</param>
        /// <param name="state">防止CSRF攻击,成功授权后回调时会原样带回</param>
        /// <returns>Dictionary</returns>
        public static Dictionary<string, object> GetAccessToken(string code, string state)
        {
            string send_url = WeChatDefaults.AccessTokenEndpoint
                + "?appid=" + WeChatDefaults.AppId
                + "&secret=" + WeChatDefaults.AppSecret
                + "&code=" + code 
                + "&state=" + state
                + "&grant_type=authorization_code";
            //发送并接受返回值
            using (HttpClient client = new HttpClient())
            {
                var result = client.GetStringAsync(send_url);
                if (string.IsNullOrEmpty(result.Result) && (result.Result.Contains("errmsg")|| result.Result.Contains("errmsg")))
                {
                    return null;
                }
                try
                {
                    Dictionary<string, object> dic = JsonConvert.DeserializeObject<Dictionary<string, object>>(result.Result);
                    return dic;
                }
                catch
                {
                    return null;
                }
            }                
        }

        /// <summary>
        /// 根据access_token判断access_token是否过期
        /// </summary>
        /// <param name="access_token"></param>
        /// <returns>true表示未失效</returns>
        public static bool CheckAccessToken(string access_token)
        {
            string send_url = WeChatDefaults.AccessTokenEndpoint + "?access_token=" + access_token + "&openid=" + string.Empty;
            //发送并接受返回值
            using (HttpClient client = new HttpClient())
            {
                var result = client.GetStringAsync(send_url);
                if (!string.IsNullOrEmpty(result.Result) && !(result.Result.Contains("errmsg") || result.Result.Contains("errmsg")))
                {
                    try
                    {
                        Dictionary<string, object> dic = JsonConvert.DeserializeObject<Dictionary<string, object>>(result.Result);
                        if (dic.ContainsKey("errmsg"))
                        {
                            if (dic["errmsg"].ToString() == "ok")
                            {
                                return true;
                            }
                            else
                            {
                                return false;
                            }
                        }
                        return false;
                    }
                    catch
                    {
                        return false;
                    }
                }
                else
                {
                    return false;
                }
            }                
        }

        /// <summary>
        /// 若fresh_token已过期则根据refresh_token取得新的refresh_token
        /// </summary>
        /// <param name="refresh_token">refresh_token</param>
        /// <returns>Dictionary</returns>
        public static Dictionary<string, object> GetRefreshToken(string refresh_token)
        {
            string send_url = WeChatDefaults.RefreshTokenEndpoint 
                + "?appid=" + WeChatDefaults.AppId 
                + "&grant_type=refresh_token&refresh_token=" + refresh_token;
            //发送并接受返回值
            using (HttpClient client = new HttpClient())
            {
                var result = client.GetStringAsync(send_url);
                if (!string.IsNullOrEmpty(result.Result) && !(result.Result.Contains("errmsg") || result.Result.Contains("errmsg")))
                {
                    return null;
                }
                try
                {
                    Dictionary<string, object> dic = JsonConvert.DeserializeObject<Dictionary<string, object>>(result.Result);
                    return dic;
                }
                catch
                {
                    return null;
                }
            }                
        }

        /// <summary>
        /// 获取登录用户自己的基本资料
        /// </summary>
        /// <param name="access_token">临时的Access Token</param>
        /// <param name="open_id">用户openid</param>
        /// <returns>Dictionary</returns>
        public static Dictionary<string, object> GetUserInfo(string access_token, string open_id)
        {
            //发送并接受返回值 
            string send_url = WeChatDefaults.UserInformationEndpoint + "?access_token=" + access_token + "&openid=" + open_id;
            //发送并接受返回值
            using (HttpClient client = new HttpClient())
            {
                var result = client.GetStringAsync(send_url);
                if (!string.IsNullOrEmpty(result.Result) && !(result.Result.Contains("errmsg") || result.Result.Contains("errmsg")))
                {
                    return null;
                }
                Dictionary<string, object> dic = JsonConvert.DeserializeObject<Dictionary<string, object>>(result.Result);
                return dic;
            }                
        }
    }

4.WeChatDefault.cs

public static class WeChatDefaults
    {
        public const string AuthenticationScheme = "WeChat";

        /// <summary>
        ///  开放平台申请审核后发放的AppId
        /// </summary>
        public const string AppId = "企业申请的AppId ";

        /// <summary>
        /// 开放平台申请审核后发放的**
        /// </summary>
        public const string AppSecret = "企业申请的AppSecret ";

        /// <summary>
        /// 开放平台申请的回调域名
        /// </summary>
        public const string RedirectUri = "we-focus.cn";

        /// <summary>
        /// 认证接口
        /// </summary>
        public static readonly string AuthorizationEndpoint = "https://open.weixin.qq.com/connect/oauth2/authorize";

        /// <summary>
        /// 认证接口二维码
        /// https://open.weixin.qq.com/connect/qrconnect?appid=wxf1f84ee1c835dc1e&redirect_uri=http%3a%2f%2fwe-focus.cn&response_type=code&scope=snsapi_login&state=state#wechat_redirect
        /// </summary>
        public static readonly string AuthorizationQrEndpoint = "https://open.weixin.qq.com/connect/qrconnect";

        /// <summary>
        /// 通过code获取access_token 接口
        /// https://api.weixin.qq.com/sns/oauth2/access_token?appid=wxf1f84ee1c835dc1e&secret=a0b7f9516303199ea3fe3b39f7a930b0&code=CODE&grant_type=authorization_code
        /// </summary>
        public static readonly string AccessTokenEndpoint = "https://api.weixin.qq.com/sns/oauth2/access_token";

        /// <summary>
        /// 刷新token 接口
        /// https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=wxf1f84ee1c835dc1e&grant_type=refresh_token&refresh_token=REFRESH_TOKEN
        /// </summary>
        public static readonly string RefreshTokenEndpoint = "https://api.weixin.qq.com/sns/oauth2/refresh_token";

        /// <summary>
        /// 用户信息接口
        /// https://api.weixin.qq.com/sns/userinfo?access_token=access_token&openid=open_id;
        /// </summary>
        public static readonly string UserInformationEndpoint = "https://api.weixin.qq.com/sns/userinfo";
}

5.WeChatToken.cs

public class WeChatTocken
    {
        /// <summary>
        /// 接口调用凭证
        /// </summary>
        public string Access_Token { get; set; }

        /// <summary>
        /// access_token接口调用凭证超时时间,单位(秒)
        /// </summary>
        public int Expires_In { get; set; }

        /// <summary>
        /// 用户刷新access_token
        /// </summary>
        public string Refresh_Token { get; set; }

        /// <summary>
        /// 授权用户唯一标识
        /// </summary>
        public string OpenId { get; set; }

        /// <summary>
        /// 用户授权的作用域,使用逗号(,)分隔
        /// </summary>
        public string Scope { get; set; }

        /// <summary>
        /// 当且仅当该网站应用已获得该用户的userinfo授权时,才会出现该字段。
        /// </summary>
        public string UnionId { get; set; }
    }

6.WeChatUserInfo.cs

public class WeChatUserInfo
    {
        /// <summary>
        /// 授权用户唯一标识
        /// </summary>
        public string OpenId { get; set; }

        /// <summary>
        /// 昵称
        /// </summary>
        public string NickName { get; set; }

        /// <summary>
        /// 性别
        /// </summary>
        public int Sex { get; set; }

        /// <summary>
        /// 头像路径
        /// </summary>
        public string HeadImgUrl { get; set; }

        /// <summary>
        /// 省份
        /// </summary>
        public string Province { get; set; }

        /// <summary>
        /// 城市
        /// </summary>
        public string City { get; set; }

        /// <summary>
        /// 国家
        /// </summary>
        public string Country { get; set; }

        /// <summary>
        /// 特权
        /// </summary>
        public string[] Privilege { get; set; }

        /// <summary>
        /// 当且仅当该网站应用已获得该用户的userinfo授权时,才会出现该字段。
        /// </summary>
        public string UnionId { get; set; }
    }

三、参考连接

微信登录 官方开发文档 https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html

学习记录一下,欢迎大神们指导。

相关标签: c# 后端 asp.net

上一篇:

下一篇: