init commit
This commit is contained in:
12
20220330_Vote/Ewide.Core/OAuth/IWechatOAuth.cs
Normal file
12
20220330_Vote/Ewide.Core/OAuth/IWechatOAuth.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.OAuth
|
||||
{
|
||||
public interface IWechatOAuth
|
||||
{
|
||||
Task<TokenModel> GetAccessTokenAsync(string code, string state = "");
|
||||
string GetAuthorizeUrl(string state = "");
|
||||
Task<UserInfoModel> GetUserInfoAsync(string accessToken, string openId);
|
||||
Task<TokenModel> GetRefreshTokenAsync(string refreshToken);
|
||||
}
|
||||
}
|
||||
49
20220330_Vote/Ewide.Core/OAuth/OAuthConfig.cs
Normal file
49
20220330_Vote/Ewide.Core/OAuth/OAuthConfig.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace Ewide.Core.OAuth
|
||||
{
|
||||
/// <summary>
|
||||
/// OAuth配置---此结构方便拓展
|
||||
/// </summary>
|
||||
public class OAuthConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// AppId
|
||||
/// </summary>
|
||||
public string AppId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Secret Key
|
||||
/// </summary>
|
||||
public string AppKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 回调地址
|
||||
/// </summary>
|
||||
public string RedirectUri { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 权限范围
|
||||
/// </summary>
|
||||
public string Scope { get; set; }
|
||||
|
||||
public static OAuthConfig LoadFrom(IConfiguration configuration, string prefix)
|
||||
{
|
||||
return With(appId: configuration[prefix + ":app_id"],
|
||||
appKey: configuration[prefix + ":app_key"],
|
||||
redirectUri: configuration[prefix + ":redirect_uri"],
|
||||
scope: configuration[prefix + ":scope"]);
|
||||
}
|
||||
|
||||
private static OAuthConfig With(string appId, string appKey, string redirectUri, string scope)
|
||||
{
|
||||
return new OAuthConfig()
|
||||
{
|
||||
AppId = appId,
|
||||
AppKey = appKey,
|
||||
RedirectUri = redirectUri,
|
||||
Scope = scope
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
67
20220330_Vote/Ewide.Core/OAuth/TokenModel.cs
Normal file
67
20220330_Vote/Ewide.Core/OAuth/TokenModel.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Ewide.Core.OAuth
|
||||
{
|
||||
/// <summary>
|
||||
/// AccessToken参数
|
||||
/// </summary>
|
||||
public class TokenModel
|
||||
{
|
||||
/// <summary>
|
||||
/// 用户标识
|
||||
/// </summary>
|
||||
[JsonPropertyName("openid")]
|
||||
public string OpenId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Token 类型
|
||||
/// </summary>
|
||||
[JsonPropertyName("token_type")]
|
||||
public string TokenType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// AccessToken
|
||||
/// </summary>
|
||||
[JsonPropertyName("access_token")]
|
||||
public string AccessToken { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用于刷新 AccessToken 的 Token
|
||||
/// </summary>
|
||||
[JsonPropertyName("refresh_token")]
|
||||
public string RefreshToken { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 此 AccessToken 对应的权限
|
||||
/// </summary>
|
||||
[JsonPropertyName("scope")]
|
||||
public string Scope { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// AccessToken 过期时间
|
||||
/// </summary>
|
||||
[JsonPropertyName("expires_in")]
|
||||
public dynamic ExpiresIn { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 错误的详细描述
|
||||
/// </summary>
|
||||
[JsonPropertyName("error_description")]
|
||||
public string ErrorDescription { get; set; }
|
||||
}
|
||||
|
||||
public static class AccessTokenModelModelExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取的Token是否包含错误
|
||||
/// </summary>
|
||||
/// <param name="accessTokenModel"></param>
|
||||
/// <returns></returns>
|
||||
public static bool HasError(this TokenModel accessTokenModel)
|
||||
{
|
||||
return accessTokenModel == null ||
|
||||
string.IsNullOrEmpty(accessTokenModel.AccessToken) ||
|
||||
!string.IsNullOrEmpty(accessTokenModel.ErrorDescription);
|
||||
}
|
||||
}
|
||||
}
|
||||
62
20220330_Vote/Ewide.Core/OAuth/UserInfoModel.cs
Normal file
62
20220330_Vote/Ewide.Core/OAuth/UserInfoModel.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Ewide.Core.OAuth
|
||||
{
|
||||
/// <summary>
|
||||
/// 微信用户参数
|
||||
/// </summary>
|
||||
public class UserInfoModel
|
||||
{
|
||||
[JsonPropertyName("nickname")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonPropertyName("headimgurl")]
|
||||
public string Avatar { get; set; }
|
||||
|
||||
[JsonPropertyName("language")]
|
||||
public string Language { get; set; }
|
||||
|
||||
[JsonPropertyName("openid")]
|
||||
public string Openid { get; set; }
|
||||
|
||||
[JsonPropertyName("sex")]
|
||||
public int Sex { get; set; }
|
||||
|
||||
[JsonPropertyName("province")]
|
||||
public string Province { get; set; }
|
||||
|
||||
[JsonPropertyName("city")]
|
||||
public string City { get; set; }
|
||||
|
||||
[JsonPropertyName("country")]
|
||||
public string Country { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户特权信息,json 数组,如微信沃卡用户为(chinaunicom)
|
||||
/// </summary>
|
||||
[JsonPropertyName("privilege")]
|
||||
public List<string> Privilege { get; set; }
|
||||
|
||||
[JsonPropertyName("unionid")]
|
||||
public string UnionId { get; set; }
|
||||
|
||||
[JsonPropertyName("errmsg")]
|
||||
public string ErrorMessage { get; set; }
|
||||
}
|
||||
|
||||
public static class UserInfoModelExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取的用户是否包含错误
|
||||
/// </summary>
|
||||
/// <param name="userInfoModel"></param>
|
||||
/// <returns></returns>
|
||||
public static bool HasError(this UserInfoModel userInfoModel)
|
||||
{
|
||||
return userInfoModel == null ||
|
||||
string.IsNullOrEmpty(userInfoModel.Name) ||
|
||||
!string.IsNullOrEmpty(userInfoModel.ErrorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
102
20220330_Vote/Ewide.Core/OAuth/WechatOAuth.cs
Normal file
102
20220330_Vote/Ewide.Core/OAuth/WechatOAuth.cs
Normal file
@@ -0,0 +1,102 @@
|
||||
using Furion.DependencyInjection;
|
||||
using Furion.FriendlyException;
|
||||
using Furion.RemoteRequest.Extensions;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.OAuth
|
||||
{
|
||||
public class WechatOAuth : IWechatOAuth, ISingleton
|
||||
{
|
||||
private readonly string _authorizeUrl = "https://open.weixin.qq.com/connect/oauth2/authorize";
|
||||
private readonly string _accessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token";
|
||||
private readonly string _refreshTokenUrl = "https://api.weixin.qq.com/sns/oauth2/refresh_token";
|
||||
private readonly string _userInfoUrl = "https://api.weixin.qq.com/sns/userinfo";
|
||||
|
||||
private readonly OAuthConfig _oauthConfig;
|
||||
|
||||
public WechatOAuth(IConfiguration configuration)
|
||||
{
|
||||
_oauthConfig = OAuthConfig.LoadFrom(configuration, "oauth:wechat");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发起授权
|
||||
/// </summary>
|
||||
/// <param name="state"></param>
|
||||
/// <returns></returns>
|
||||
public string GetAuthorizeUrl(string state = "")
|
||||
{
|
||||
var param = new Dictionary<string, string>()
|
||||
{
|
||||
["appid"] = _oauthConfig.AppId,
|
||||
["redirect_uri"] = _oauthConfig.RedirectUri,
|
||||
["response_type"] = "code",
|
||||
["scope"] = _oauthConfig.Scope,
|
||||
["state"] = state
|
||||
};
|
||||
return $"{_authorizeUrl}?{param.ToQueryString()}#wechat_redirect";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取微信Token
|
||||
/// </summary>
|
||||
/// <param name="code"></param>
|
||||
/// <param name="state"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<TokenModel> GetAccessTokenAsync(string code, string state = "")
|
||||
{
|
||||
var param = new Dictionary<string, string>()
|
||||
{
|
||||
["appid"] = _oauthConfig.AppId,
|
||||
["secret"] = _oauthConfig.AppKey,
|
||||
["code"] = code,
|
||||
["grant_type"] = "authorization_code"
|
||||
};
|
||||
var accessTokenModel = await $"{_accessTokenUrl}?{param.ToQueryString()}".GetAsAsync<TokenModel>();
|
||||
if (accessTokenModel.HasError())
|
||||
throw Oops.Oh($"{ accessTokenModel.ErrorDescription}");
|
||||
return accessTokenModel;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取微信用户基本信息
|
||||
/// </summary>
|
||||
/// <param name="accessToken"></param>
|
||||
/// <param name="openId"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<UserInfoModel> GetUserInfoAsync(string accessToken, string openId)
|
||||
{
|
||||
var param = new Dictionary<string, string>()
|
||||
{
|
||||
["access_token"] = accessToken,
|
||||
["openid"] = openId,
|
||||
["lang"] = "zh_CN",
|
||||
};
|
||||
var userInfoModel = await $"{_userInfoUrl}?{param.ToQueryString()}".GetAsAsync<UserInfoModel>();
|
||||
if (userInfoModel.HasError())
|
||||
throw Oops.Oh($"{ userInfoModel.ErrorMessage}");
|
||||
return userInfoModel;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 刷新微信Token
|
||||
/// </summary>
|
||||
/// <param name="refreshToken"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<TokenModel> GetRefreshTokenAsync(string refreshToken)
|
||||
{
|
||||
var param = new Dictionary<string, string>()
|
||||
{
|
||||
["appid"] = _oauthConfig.AppId,
|
||||
["grant_type"] = "refresh_token",
|
||||
["refresh_token"] = refreshToken
|
||||
};
|
||||
var refreshTokenModel = await $"{_refreshTokenUrl}?{param.ToQueryString()}".GetAsAsync<TokenModel>();
|
||||
if (refreshTokenModel.HasError())
|
||||
throw Oops.Oh($"{ refreshTokenModel.ErrorDescription}");
|
||||
return refreshTokenModel;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user