C#实现的微信网页授权操作逻辑封装示例

时间:2021-11-21 10:53:30

本文实例讲述了C#实现的微信网页授权操作逻辑封装。分享给大家供大家参考,具体如下:

一、微信网页授权登录

前提:

1.已经获取的接口权限,如果是测试账号就已经有权限了

2.配置接口的授权域名

更多说明可以参考方倍工作室:http://www.cnblogs.com/txw1958/p/weixin71-oauth20.html

或者官网API:http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html

步骤:

1.用户同意授权,获取code

2.根据code 获取access_token及当前操作用户的openid、unionid

3.根据openid获取用户基本信息(如果需要的话)

注:如果想在网站使用扫一扫,授权登录,可以讲 _oauth.GetCodeUrl() 授权地址生成二维码来使用

C#封装微信网页授权登录使用实例:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
string appid = "wx145b4a8fd07b24e8";
string appsecrect = "fe6951dcb99772411c42f724b1336065";
string redirect_url = "配置域名下的回调地址";
OAuthManage _oauth = null;
/// <summary>
///控制器构造函数
/// </summary>
public UserController()
{
  _oauth = new OAuthManage(appid, appsecrect, redirect_url);
}
/// <summary>
/// 授权登录
/// </summary>
/// <returns></returns>
public ActionResult AuthLogin()
{
  ViewBag.url = _oauth.GetCodeUrl();
  return View();
}
/// <summary>
/// 回调处理
/// </summary>
/// <returns></returns>
public ActionResult OAuthHandle()
{
  string result = "";
  //注册事件处理
  _oauth.OnError = (e) =>
  {
    string msg = "";
    Exception inner = e;
    while (inner != null)
    {
      msg += inner.Message;
      inner = inner.InnerException;
    }
    result = msg;
    LogOperate.Write(msg);
  };
  _oauth.OnGetTokenSuccess = (token) =>
  {
    result += "<br/>";
    result += token.ToJsonString();
  };
  _oauth.OnGetUserInfoSuccess = (user) =>
  {
    result += "<br/>";
    result += user.ToJsonString();
  };
  //第二步
  _oauth.GetAccess_Token();
  //第三步
  _oauth.GetUserInfo();
  //显示结果
  ViewBag.msg = result;
  return View();
}

封装代码类定义:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
namespace WXPackage
{
  /// <summary>
  /// 网页授权逻辑处理,
  /// 处理三步操作,处理成功,返回用户基本信息
  /// </summary>
  public class OAuthManage
  {
    #region 基本信息定义
    /// <summary>
    /// 公众号的唯一标识
    /// </summary>
    private string appid;
    /// <summary>
    /// 公众号的appsecret
    /// </summary>
    private string secret;
    /// <summary>
    /// 回调url地址
    /// </summary>
    private string redirect_uri;
    /// <summary>
    /// 获取微信用户基本信息使用snsapi_userinfo模式
    /// 如果使用静默授权,无法获取用户基本信息但可以获取到openid
    /// </summary>
    private string scope;
    public OAuthManage(string appid, string appsecret, string redirect_uri, bool IsUserInfo = true)
    {
      this.appid = appid;
      this.secret = appsecret;
      this.redirect_uri = redirect_uri;
      this.scope = IsUserInfo ? "snsapi_userinfo" : "snsapi_base";
    }
    #endregion
    #region 请求过程信息
    /// <summary>
    /// 第一步获取到的Code 值
    /// </summary>
    public string Code { get; set; }
    /// <summary>
    /// 第二步获取到的access_token及相关数据
    /// </summary>
    public OAuthAccess_Token TokenData = null;
    #endregion
    #region 事件定义
    /// <summary>
    /// 当处理出现异常时,触发
    /// </summary>
    public Action<Exception> OnError = null;
    /// <summary>
    /// 当获取AccessToken成功是触发
    /// </summary>
    public Action<OAuthAccess_Token> OnGetTokenSuccess = null;
    /// <summary>
    /// 当获取用户信息成功时触发
    /// </summary>
    public Action<OAuthUser> OnGetUserInfoSuccess = null;
    #endregion
    #region 第二步,回调处理
    /// <summary>
    /// 第二步,通过code换取网页授权access_token
    /// </summary>
    public void GetAccess_Token()
    {
      try
      {
        //1.处理跳转
        this.Code = ReqHelper.GetString("code");
        if (string.IsNullOrEmpty(this.Code))
          throw new Exception("获取code参数失败或用户禁止授权获取基本信息");
        //1.发送获取access_token请求
        string url = GetAccess_TokenUrl();
        string result = NetHelper.Get(url);
        //2.解析相应结果
        TokenData = JsonConvert.DeserializeObject<OAuthAccess_Token>(result);
        if (TokenData == null)
          throw new Exception("反序列化结果失败,返回内容为:" + result);
        //3.获取成功
        if (OnGetTokenSuccess != null)
          OnGetTokenSuccess(TokenData);
      }
      catch (Exception ex)
      {
        Error("第二步,通过code换取网页授权access_token异常", ex);
      }
    }
    /// <summary>
    /// 刷新当前access_token
    /// </summary>
    public OAuthAccess_Token RefreshAccess_Token()
    {
      try
      {
        //1.发送请求
        string url = GetReferesh_TokenUrl();
        string result = NetHelper.Get(url);
        //2.解析结果
        OAuthAccess_Token token = JsonConvert.DeserializeObject<OAuthAccess_Token>(result);
        if (token == null)
          throw new Exception("反序列化结果失败,返回内容:" + result);
        return token;
      }
      catch (Exception ex)
      {
        Error("刷新当前access_token失败", ex);
        return null;
      }
    }
    #endregion
    #region 第三步,获取用户基本信息
    /// <summary>
    /// 第三步,获取基本信息
    /// </summary>
    public void GetUserInfo()
    {
      try
      {
        //1.发送get请求
        string url = GetUserInfoUrl();
        string result = NetHelper.Get(url);
        //2.解析结果
        OAuthUser user = JsonConvert.DeserializeObject<OAuthUser>(result);
        if (user == null)
          throw new Exception("反序列化结果失败,返回内容:" + result);
        //3.获取成功
        if (OnGetUserInfoSuccess != null)
          OnGetUserInfoSuccess(user);
      }
      catch (Exception ex)
      {
        Error("第三步、获取用户基本信息异常", ex);
      }
    }
    #endregion
    #region 静态方法
    /// <summary>
    /// 验证授权凭证是否有效
    /// </summary>
    /// <param name="access_token">access_token</param>
    /// <param name="openid">用户针对当前公众号的openid</param>
    /// <returns></returns>
    public static bool CheckWebAccess_Token(string access_token, string openid)
    {
      try
      {
        string url = string.Format("https://api.weixin.qq.com/sns/auth?access_token={0}&openid={1}",
       access_token,
       openid);
        string result = NetHelper.Get(url);
        JObject obj = JObject.Parse(result);
        int errcode = (int)obj["errcode"];
        return errcode == 0;
      }
      catch (Exception ex)
      {
        throw new Exception("," + ex.Message);
      }
    }
    #endregion
    #region 获取请求连接
    /// <summary>
    /// 获取Code的url 地址
    /// </summary>
    /// <returns></returns>
    public string GetCodeUrl()
    {
      string url = string.Format("https://open.weixin.qq.com/connect/oauth2/authorize?appid={0}&redirect_uri={1}&response_type=code&scope={2}&state=STATE#wechat_redirect",
        this.appid,
        SecurityHelper.UrlEncode(this.redirect_uri),
        this.scope);
      return url;
    }
    /// <summary>
    /// 获取access_token的url地址
    /// </summary>
    /// <returns></returns>
    private string GetAccess_TokenUrl()
    {
      string url = string.Format("https://api.weixin.qq.com/sns/oauth2/access_token?appid={0}&secret={1}&code={2}&grant_type=authorization_code",
        this.appid,
        this.secret,
        this.Code);
      return url;
    }
    /// <summary>
    /// 获取刷新AccessToke的地址
    /// </summary>
    /// <returns></returns>
    private string GetReferesh_TokenUrl()
    {
      string url = string.Format("https://api.weixin.qq.com/sns/oauth2/refresh_token?appid={0}&grant_type=refresh_token&refresh_token={1}",
        this.appid,
        this.TokenData.refresh_token
        );
      return url;
    }
    /// <summary>
    /// 获取用户基本信息地址
    /// </summary>
    /// <returns></returns>
    private string GetUserInfoUrl()
    {
      string url = string.Format("https://api.weixin.qq.com/sns/userinfo?access_token={0}&openid={1}&lang=zh_CN",
        this.TokenData.access_token,
        this.TokenData.openid);
      return url;
    }
    #endregion
    private void Error(string msg, Exception inner)
    {
      if (this.OnError != null)
      {
        this.OnError(new Exception(msg, inner));
      }
    }
  }
  /// <summary>
  /// 授权之后获取用户基本信息
  /// </summary>
  public class OAuthUser
  {
    public string openid { get; set; }
    public string nickname { get; set; }
    public int sex { get; set; }
    public string province { get; set; }
    public string city { get; set; }
    public string country { get; set; }
    public string headimgurl { get; set; }
    /// <summary>
    /// 用户特权信息,json 数组
    /// </summary>
    public JArray privilege { get; set; }
    public string unionid { get; set; }
  }
  /// <summary>
  /// 获取Access_Token或者刷新返回的数据对象
  /// </summary>
  public class OAuthAccess_Token
  {
    public string access_token { get; set; }
    public int expires_in { get; set; }
    public string refresh_token { get; set; }
    /// <summary>
    /// 用户针对当前公众号的唯一标识
    /// 关注后会产生,返回公众号下页面也会产生
    /// </summary>
    public string openid { get; set; }
    public string scope { get; set; }
    /// <summary>
    /// 当前用户的unionid,只有在用户将公众号绑定到微信开放平台帐号后
    /// </summary>
    public string unionid { get; set; }
  }
}

希望本文所述对大家C#程序设计有所帮助。