微信开放平台之网站授权微信登录功能

 更新时间:2015年09月24日 11:22:29   作者:小 鹏  
本文通过.net实现的微信开放平台之网站授权微信登录功能,需要的小伙伴一起看看吧

1 微信开放平台:https://open.weixin.qq.com/

2 微信官方教程:https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419316505&token=&lang=zh_CN

3.pc页面显示

4. 通过官方提供的文档,我们可以看出一共分4个步骤

第一步:请求CODE

第二步:通过code获取access_token

第三步:通过access_token调用接口

第4步:获取用户个人信息(UnionID机制)

api:核心代码

public class weixin_helper
 {
  public weixin_helper()
  {
  }
  /// <summary>
  /// 根据AppID和AppSecret获得access token(默认过期时间为2小时)
  /// </summary>
  /// <returns>Dictionary</returns>
  public static Dictionary<string, object> get_access_token()
  {
   //获得配置信息
   oauth_config config = oauth_helper.get_config(2);
   string send_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" +
        config.oauth_app_id + "&secret=" + config.oauth_app_key + "";
   //发送并接受返回值
   string result = Utils.HttpGet(send_url);
   if (result.Contains("errmsg"))
   {
    return null;
   }
   try
   {
    Dictionary<string, object> dic = JsonConvert.DeserializeObject<Dictionary<string, object>>(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> get_access_token(string code, string state)
  {
   //获得配置信息
   oauth_config config = oauth_helper.get_config(2);
   string send_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" +
        config.oauth_app_id + "&secret=" + config.oauth_app_key + "&code="+code+"&grant_type=authorization_code";
   //发送并接受返回值
   string result = Utils.HttpGet(send_url);
   if (result.Contains("errmsg"))
   {
    return null;
   }
   try
   {
    Dictionary<string, object> dic = JsonConvert.DeserializeObject<Dictionary<string, object>>(result);
    return dic;
   }
   catch
   {
    return null;
   }
  }
  /// <summary>
  /// 根据access_token判断access_token是否过期
  /// </summary>
  /// <param name="access_token"></param>
  /// <returns>true表示未失效</returns>
  public static bool check_access_token(string access_token)
  {
   //获得配置信息
   oauth_config config = oauth_helper.get_config(2);
   string send_url = "https://api.weixin.qq.com/sns/auth?access_token=" + access_token + "&openid=" + config.oauth_app_id;
   //发送并接受返回值
   string result = Utils.HttpGet(send_url);
   try
   {
    Dictionary<string, object> dic = JsonConvert.DeserializeObject<Dictionary<string, object>>(result);
    if (dic.ContainsKey("errmsg"))
    {
     if (dic["errmsg"].ToString()=="ok")
     {
      return true;
     }
     else
     {
      return false;
     }
    }
    return false;
   }
   catch
   {
    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> get_refresh_token(string refresh_token)
  {
   //获得配置信息
   oauth_config config = oauth_helper.get_config(2);
   string send_url =
    "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=" +
        config.oauth_app_id + "&grant_type=refresh_token&refresh_token=" + refresh_token;
   //发送并接受返回值
   string result = Utils.HttpGet(send_url);
   if (result.Contains("errmsg"))
   {
    return null;
   }
   try
   {
    Dictionary<string, object> dic = JsonConvert.DeserializeObject<Dictionary<string, object>>(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> get_user_info(string access_token, string open_id)
  {
   //获得配置信息
   oauth_config config = oauth_helper.get_config(2);
   //发送并接受返回值 
   string send_url = "https://api.weixin.qq.com/sns/userinfo?access_token="+access_token+"&openid="+open_id;
   //发送并接受返回值
   string result = Utils.HttpGet(send_url);
   if (result.Contains("errmsg"))
   {
    return null;
   }
   //反序列化JSON
   Dictionary<string, object> dic = JsonHelper.DataRowFromJSON(result);
   return dic;
  }
 }

控制器的核心代码:

#region 微信登录
  /// <summary>
  /// 微信登录
  /// </summary>
  public ActionResult WeChat()
  {
   //获得配置信息
   oauth_config config = oauth_helper.get_config(2); //主键id
   if (config == null)
   {
    return Content("出错了,您尚未配置微信相关的API信息!");
   }
   string state = Guid.NewGuid().ToString().Replace("-", "");
   Session["oauth_state"] = state;
   string send_url =
    "https://open.weixin.qq.com/connect/qrconnect?appid=" + config.oauth_app_id +
        "&redirect_uri=" + Utils.UrlEncode(config.return_uri.ToLower()) +
        "&response_type=code&scope=snsapi_login&state=" + state +
        "#wechat_redirect";
   //开始发送
   return Redirect(send_url); //跳转到微信自己 指定的关联登陆页面
  }
  /// <summary>
  /// 微信登录返回action
  /// </summary>
  public ActionResult WeChatReturnUrl(string state, string code)
  {
   //取得返回参数
   string access_token = string.Empty;
   string expires_in = string.Empty;
   string client_id = string.Empty;
   string openid = string.Empty;
   string refresh_token = string.Empty;
   if (Session["oauth_state"] == null || Session["oauth_state"].ToString() == "" ||
    state != Session["oauth_state"].ToString() || string.IsNullOrEmpty(code))//若返回参数中未包含code或者state没有通过验证则提示出错
   {
    return Content("出错啦,state未初始化!");
   }
   //第一步:通过code来获取Access Token以及openid
   Dictionary<string, object> dic1 = weixin_helper.get_access_token(code, state);
   if (dic1 == null || !dic1.ContainsKey("access_token"))
   {
    return Content("错误代码:,无法获取Access Token,请检查App Key是否正确!");
   }
   if (dic1 == null || !dic1.ContainsKey("openid"))
   {
    if (dic1.ContainsKey("errmsg"))
    {
     return Content("errcode:" + dic1["errcode"] + ",errmsg:" + dic1["errmsg"]);
    }
    else
    {
     return Content("出错啦,无法获取用户授权Openid!");
    }
   }
   access_token = dic1["access_token"].ToString();//获取access_token
   expires_in = dic1["expires_in"].ToString();//获取过期时间
   refresh_token = dic1["refresh_token"].ToString();//获取用于重新刷新access_token的凭证
   openid = dic1["openid"].ToString();//用户唯一标示openid
   //储存获取数据用到的信息
   Session["oauth_name"] = "webchat";
   Session["oauth_access_token"] = access_token;
   Session["oauth_openid"] = openid;
   Session["oauth_refresh_token"] = refresh_token;
   #region todo 将获取到的用户信息保存到数据库中
   #endregion
   //第二步:通过Access Token以及openid来获取用户的基本信息
   //Dictionary<string, object> dic2 = weixin_helper.get_user_info(access_token,openid);
   //第三步:跳转到指定页面
   return Content(WeChatResultJson());
  }
  /// <summary>
  /// 微信登录返回action, 处理用户信息
  /// </summary>
  public string WeChatResultJson()
  {
   string oauth_access_token = string.Empty;
   string oauth_openid = string.Empty;
   string oauth_name = string.Empty;
   string oauth_refresh_token = string.Empty;
   if (Session["oauth_name"] == null || Session["oauth_access_token"] == null ||
    Session["oauth_openid"] == null)
   {
    return "{\"ret\":\"1\", \"msg\":\"出错啦,Access Token已过期或不存在!\"}";
   }
   oauth_name = Session["oauth_name"].ToString();
   oauth_access_token = Session["oauth_access_token"].ToString();
   oauth_openid = Session["oauth_openid"].ToString();
   oauth_refresh_token = Session["oauth_refresh_token"].ToString();
   if (!weixin_helper.check_access_token(oauth_access_token)) //调用access_token前需判断是否过期
   {
    Dictionary<string, object> dic1 = weixin_helper.get_refresh_token(oauth_refresh_token);//如果已过期则重新换取新的access_token
    if (dic1 == null || !dic1.ContainsKey("access_token"))
    {
     return "{\"openid\":\"0\", \"msg\":\"出错啦,无法获取access_token!\"}";
    }
    oauth_access_token = dic1["access_token"].ToString();
   }
   Dictionary<string, object> dic = weixin_helper.get_user_info(oauth_access_token, oauth_openid);
   if (dic == null)
   {
    return "{\"openid\":\"0\", \"msg\":\"出错啦,无法获取授权用户信息!\"}";
   }
   try
   {
    StringBuilder str = new StringBuilder();
    str.Append("{");
    str.Append("\"openid\": \"" + dic["openid"].ToString() + "\", ");
    str.Append("\"nickname\": \"" + dic["nickname"].ToString() + "\", ");
    str.Append("\"sex\": \"" + dic["sex"].ToString() + "\", ");
    str.Append("\"province\": \"" + dic["province"].ToString() + "\", ");
    str.Append("\"city\": \"" + dic["city"].ToString() + "\", ");
    str.Append("\"country\": \"" + dic["country"].ToString() + "\", ");
    str.Append("\"headimgurl\": \"" + dic["headimgurl"].ToString() + "\", ");
    str.Append("\"privilege\": \"" + dic["privilege"].ToString() + "\", ");
    str.Append("\"unionid\": \"" + dic["unionid"].ToString() + "\"");
    str.Append("\"oauth_name\": \"" + oauth_name + "\"");
    str.Append("\"oauth_access_token\": \"" + oauth_access_token + "\"");
    str.Append("\"oauth_openid\": \"" + oauth_openid + "\"");
    str.Append("}");
    return str.ToString();
   }
   catch
   {
    return "{\"ret\":\"0\", \"msg\":\"出错啦,无法获取授权用户信息!\"}";
   }
  }
  #endregion

相关文章

  • C# WinForm打开PDF文件并在窗体中显示

    C# WinForm打开PDF文件并在窗体中显示

    本文主要介绍通过引用Adobe reader提供的COM组件,以实现在WinForm程序中显示PDF文件的功能。
    2016-05-05
  • C# Request.Form用法案例详解

    C# Request.Form用法案例详解

    这篇文章主要介绍了C# Request.Form用法案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • c#通过ip获取地理信息

    c#通过ip获取地理信息

    这篇文章主要介绍了c#通过ip获取地理信息的方法,这里是通过cz88和ip138查询的
    2014-01-01
  • C#中string.Empty和null的区别详解

    C#中string.Empty和null的区别详解

    这篇文章主要介绍了C#中string.Empty和null的区别详解,本文同时讲解了空字符串和Empty的区别以及string.Empty与null的区别,需要的朋友可以参考下
    2015-06-06
  • C#中多态性的实现

    C#中多态性的实现

    这篇文章主要介绍了C#中多态性的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-02-02
  • C#定时每天00点00分00秒自动重启软件

    C#定时每天00点00分00秒自动重启软件

    这篇文章主要为大家详细介绍了C#定时每天00点00分00秒自动重启软件,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-08-08
  • 解析在内部循环中Continue外部循环的使用详解

    解析在内部循环中Continue外部循环的使用详解

    本篇文章是对在内部循环中Continue外部循环的使用进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • C#中foreach循环对比for循环的优势和劣势

    C#中foreach循环对比for循环的优势和劣势

    循环语句是编程的基本语句,在C#中除了沿用C语言的循环语句外,还提供了foreach语句来实现循环,下面这篇文章主要给大家介绍了关于C#中foreach循环对比for循环的优势和劣势,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-09-09
  • C#中缓存的基本使用方法

    C#中缓存的基本使用方法

    项目开发过程中缓存的应用到处可见,下面这篇文章主要给大家介绍了关于C#中缓存的基本使用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-09-09
  • C#实现远程关闭计算机或重启计算机的方法

    C#实现远程关闭计算机或重启计算机的方法

    这篇文章主要介绍了C#实现远程关闭计算机或重启计算机的方法,涉及C#远程连接及系统命令的调用技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-08-08

最新评论