asp.net 、C#实现微信企业号OAuth2认证
以微信企业号作为入口的应用,几乎都会遇到需要应用系统中个人信息和微信用户关联问题、从而进行其他业务处理。目前所做项目采取在企业号通讯录添加自定义字段存入应用系统用户信息表中唯一标识UserGuid进行关联。那么如何获取微信企业号通讯录存储的自定义字段、从而实现应用用户信息和微信账号关联?把实现方案大致整理一下,如有不足,还望指出:
1:在企业号通讯录内添加用户Guid唯一字段。
2:创建应用并启用回调模式
3:以微信为入口的应用验证用户的方法,首先在用户访问应用主页时判断Cookie是否有UserGuid信息,如果没有则调用微信OAuth2认证接口。redirectUrl参数是回调页面地址,通过认证后会返回redirectUrl?code=XXXX信息。注:RedirectUrl回调地址必须是外网可以访问的。
1 if (Request.Cookies["UserGuid"] == null) 2 { 3 string httpUrl = 4 "https://open.weixin.qq.com/connect/oauth2/authorize?appid=XX&redirect_uri=URL&response_type=code&scope=snsapi_base&state="; 5 Response.Redirect(httpUrl); 6 } 7 else 8 { 9 //TODO 获取userguid之后处理步骤 Request.Cookies["UserGuid"].ToString(); 10 11 }
4:回调页面处理思路
4.1首先获取通过认证后的Code参数,之后根据企业号的CorpID和Secret获取AccessToken。
Https请求方式: GET
https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=id&corpsecret=secrect
成功时返回:
{
"access_token": "XXX…………",
"expires_in": 7200
}
4.2获取token之后,根据code和accesstoken字符串参数获取微信用户信息,accesstoken7200秒内有效,code参数五分钟内有效且仅能使用一次。
Https请求方式: GET
https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token=ACCESS_TOKEN&code=CODE
验证为企业成员时返回
{
"UserId":"USERID",
"DeviceId":"DEVICEID"
}
请求失败时返回
{
"errcode": "40029",
"errmsg": "invalid code"
}
4.3获取UerID之后,根据access_token和UerID获取用户通讯录中信息。自定义字段在extattr属性中。
Https请求方式: GET
https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN&userid=UerID
成功时返回
{
"errcode": 0,
"errmsg": "ok",
"userid": "zhangsan",
"name": "XX",
"department": [2],
"position": "XX",
"mobile": "XX",
"gender": "1",
"email": "XX",
"weixinid": "XX",
"avatar": "XX",
"status": 1,
"extattr": {"attrs":[{"name":"用户自定义字段名","value":"自定义字段值"}]}
}
4.4获取用户自定义字段UserGuid后存入cookie,并返回应用主页面。主页面此时验证Cookie,userguid信息。
5:回调页面代码C#
1 protected void Page_Load(object sender, EventArgs e) 2 { 3 4 try 5 { 6 //1.微信主页判断是否存在Cookie信息,如果存在则不需要再次验证 7 //2.如果不存在,则跳转到微信OAuth统一认证页面认证,之后到此页面获取用户信息存入Cookie返回主页 8 //3.获取Code,此code只能使用一次。 9 string code = Request["code"]; 10 11 //4.根据企业ID:XX,Secret:XXX,获取token 12 string accessTokenUrl = "https://qyapi.weixin.qq.com/cgi-bin/gettoken"; 13 string accessTokenResult = HttpGet(accessTokenUrl, "corpid=XX&corpsecret=XXXX"); 14 JavaScriptSerializer js = new JavaScriptSerializer(); 15 token mytoken = js.Deserialize<token>(accessTokenResult); 16 string tokenValue = mytoken.access_token; 17 18 //5.获取UserInfo,包含userId 19 string userinfoUrl = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo"; 20 string userinfojson = HttpGet(userinfoUrl, "access_token=" + tokenValue + "&code=" + code); 21 userinfo userinfo1 = js.Deserialize<userinfo>(userinfojson); 22 string UserId = userinfo1.UserId; 23 24 //6.根据userId获取通讯录中用户的详细信息 25 string userinfodetailURL = "https://qyapi.weixin.qq.com/cgi-bin/user/get"; 26 string userinfodetailResult = HttpGet(userinfodetailURL, "access_token=" + tokenValue + "&userid=" + UserId); 27 JObject jObject = (JObject)JsonConvert.DeserializeObject(userinfodetailResult); 28 JObject ja = (JObject)JsonConvert.DeserializeObject(jObject["extattr"].ToString()); 29 JArray jObject1 = (JArray)JsonConvert.DeserializeObject(ja["attrs"].ToString()); 30 //txtReturn2.Text = ja[0]["MainOrganization"].ToString(); 31 32 //测试结果 33 //Response.Write("1:token:" + accessTokenResult + "<br/>2:tokenValue:" + tokenValue + "<br/>3:code:" + code + "<br/>4:userinfojson:" + userinfojson + "<br/>5.UserId:" + UserId + "<br/>6.userinfodetailResult:" + userinfodetailResult + "<br/>7:数组:" + jObject1[0]["value"].ToString()); 34 35 //7.将Guid存入cookie 36 string userguid = jObject1[0]["value"].ToString(); 37 Response.Cookies["UserGuid"].Value = userguid; 38 Response.Cookies["UserGuid"].Expires = DateTime.Now.AddDays(1); 39 //todo:跳转到微信主页 40 Response.Redirect("XX", true); 41 } 42 catch (Exception ex) 43 { 44 //TODO 处理异常 45 46 } 47 } 48 /// <summary> 49 /// 发送HttpGet请求,返回string格式的json数据 50 /// </summary> 51 /// <param name="Url"></param> 52 /// <param name="postDataStr"></param> 53 /// <returns></returns> 54 public string HttpGet(string Url, string postDataStr) 55 { 56 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url + (postDataStr == "" ? "" : "?") + postDataStr); 57 request.Method = "GET"; 58 request.ContentType = "text/html;charset=UTF-8"; 59 HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 60 Stream myResponseStream = response.GetResponseStream(); 61 StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8")); 62 string retString = myStreamReader.ReadToEnd(); 63 myStreamReader.Close(); 64 myResponseStream.Close(); 65 return retString; 66 }
6上面代码涉及到的两个类,为处理返回string类型的Json串,将json格式序列化为类。类的格式需和json保持一致。代码如下:
1 public class userinfo 2 { 3 public string UserId { get; set; } 4 public string DeviceId { get; set; } 5 } 6 7 public class token 8 { 9 10 public string access_token { get; set; } 11 public int expires_in { get; set; } 12 13 }