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学习记录一下,欢迎大神们指导。