微信平台地址:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html
注意code是在前端获取。用js直接获取到。这里有一个授权问题,如果不需要用户授权 那么只能获取到openid。如果想获取其他的用户信息,就需要用户授权。
网页获取授权登录跟在小程序里面获取的是不一样的api接口。网页无法获取到小程序里面的openid,只能通过授权活到到同一个主体的unionid。
1:获取Code
获取Code一般都是全端用js去获取。当然这里需要用到 appid。并且需要记住:这里的appid跟后面拿到code之后去获取access_token,openid 用到的code 必须是一致,否则就会提示code无效,
另外:通过网页获取openid只能通过公众号的方式获取openid,如果用户在登录的时候 绑定的openid是小程序的openid,那么这里的openid是不一样的,
(微信平台里面 公众号跟小程序的openid是不一致,但是unionid是一致的,在相同的主体下,主体就是指同一个公司下面,申请账号的时候需要有公司信息)
所以需要用到unionid去做联合登录,在用户绑定的时候就需要用unionid去绑定会员信息。
前端获取code的链接地址:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
若提示“该链接无法访问”,请检查参数是否填写错误,是否拥有scope参数对应的授权作用域权限。
获取code的微信平台地址:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html
2:通过code获取openid,这个无法获取到unionid。需要注意:这里的AppId必须跟上面获取code的appid是一致的,否则获取不到信息,
/// <summary>
/// 通过code获取openid
/// </summary>
/// <param name="code"></param>
/// <returns></returns>
public static string access_token(string code)
{
string weiPayOpenidModelJsonStr = string.Empty;
try
{
string wxAppId = ConfigurationCenterManager.Instance.WEPAY_appid;
string wxSecret = ConfigurationCenterManager.Instance.WEPAY_secret;
string args = "appid=" + wxAppId + "&" + "secret=" + wxSecret + "&" + "code=" + code + "&grant_type=authorization_code";
System.Net.WebRequest request = System.Net.WebRequest.Create("https://api.weixin.qq.com/sns/oauth2/access_token?" + args);
request.Method = "GET";
using (WebResponse response = request.GetResponse())
{
using (Stream stream = response.GetResponseStream())
{
StreamReader reader = new System.IO.StreamReader(stream);
weiPayOpenidModelJsonStr = reader.ReadToEnd();
}
}
}
catch (Exception ex)
{
AppLog.Write("获取会员信息:access_token" + ex.Message, LogMessageType.Error);
}return weiPayOpenidModelJsonStr;
}
3:第三步:由于上面的 WXOpenidModel获取到的access_token的作用域是snsapi_base,获取不到unionId,
应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息)
public M665WeChatGetTokenResult WeChatAccessToken()
{
//AppLog.Write(string.Format("调用接口WeChatAccessToken开始,参数refreshState={0}", m665.refreshState), LogMessageType.Debug);
M665WeChatGetTokenResult respMsg = new M665WeChatGetTokenResult();
//Stopwatch watch = new Stopwatch();
try
{
//开始计时
//watch.Start();
//加缓存
ICache cache = new CacheFactory().GetCache();
string access_token = null;
//将access_token和getTokenTime写在同一个缓存里面
access_token = cache.Get<string>("WeChat_AccessToken");
//cache.Remove("WeChat_AccessTokenGetTime");
string getTokenTime = cache.Get<string>("WeChat_AccessTokenGetTime");
if (access_token == null || m665.refreshState == "1" || DateTime.Compare(Convert.ToDateTime(getTokenTime).AddHours(1), DateTime.Now) < 0)
{
//直接写方法string appid = "wx330c5becf5a36a7f";
string secret = "fe15061bda4cac794c5c642d09065db3";
string postDataStr = "grant_type=client_credential" + "&appid=" + appid + "&secret=" + secret;string url ="https://api.weixin.qq.com/cgi-bin/token";
string retString = WeChatHelper.WebRequestPostOrGet(url + "?" + postDataStr, "");
JavaScriptSerializer jsv = new JavaScriptSerializer();
respMsg = jsv.Deserialize<M665WeChatGetTokenResult>(retString);
//获取成功
if (respMsg != null)
{
if (!string.IsNullOrEmpty(respMsg.access_token))
{
//成功
respMsg.result = "0";
}
else
{
//失败
respMsg.result = "1";
}
}
else
{
//失败
respMsg.result = "1";
}
if (respMsg.result == "0")
{
//将token加入缓存
cache.Add<string>("WeChat_AccessToken", respMsg.access_token, TimeSpan.FromHours(2));
//将调用时间加入缓存
cache.Add<string>("WeChat_AccessTokenGetTime", DateTime.Now.ToString(), TimeSpan.FromHours(2));
}
}
else
{
respMsg.access_token = access_token;
respMsg.result = "0";
respMsg.expires_in = "7200";
}
//结束计时
//watch.Stop();
//AppLog.Write(string.Format("调用接口WeChatAccessToken结束,用时:{0}毫秒。", watch.ElapsedMilliseconds), LogMessageType.Debug);
return respMsg;}
catch (Exception ex)
{
AppLog.Write(string.Format("调用接口WeChatAccessToken异常"), LogMessageType.Error, ex);
respMsg.result = "1";
return respMsg;
}
}
下面是一个post方法,其实跟本次讲解的流程无关,只是通过ulr调用微信平台地址返回的数据,
/// <summary>
/// Post/get 提交调用抓取
/// </summary>
/// <param name="url">提交地址</param>
/// <param name="param">参数</param>
/// <returns>string</returns>
public static string WebRequestPostOrGet(string sUrl, string sParam)
{
byte[] bt = System.Text.Encoding.UTF8.GetBytes(sParam);Uri uriurl = new Uri(sUrl);
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(uriurl);//HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(url + (url.IndexOf("?") > -1 ? "" : "?") + param);
req.Method = "Post";
req.Timeout = 120 * 1000;
req.ContentType = "application/x-www-form-urlencoded;";
req.ContentLength = bt.Length;using (Stream reqStream = req.GetRequestStream())//using 使用可以释放using段内的内存
{
reqStream.Write(bt, 0, bt.Length);
reqStream.Flush();
}
try
{
using (WebResponse res = req.GetResponse())
{
//在这里对接收到的页面内容进行处理Stream resStream = res.GetResponseStream();
StreamReader resStreamReader = new StreamReader(resStream, System.Text.Encoding.UTF8);
string resLine;
System.Text.StringBuilder resStringBuilder = new System.Text.StringBuilder();
while ((resLine = resStreamReader.ReadLine()) != null)
{
resStringBuilder.Append(resLine + System.Environment.NewLine);
}resStream.Close();
resStreamReader.Close();return resStringBuilder.ToString();
}
}
catch (Exception ex)
{
//return ex.Message;//url错误时候回报错
AppLog.Write(string.Format("调用接口WebRequestPostOrGet异常,参数sUrl={0}&sParam={1}&error={2}", sUrl, sParam), LogMessageType.Error, ex);
throw;
}
}
//第四步: 根据openid与access_token 获取unionid
/// <summary>
/// 获取unionid
/// </summary>
/// <param name="access_token"></param>
/// <param name="openid"></param>
/// <returns></returns>
public static string Get_unionid(string access_token, string openid)
{
string weixinUserInfo = string.Empty;
try
{
string key = string.Format("https://api.weixin.qq.com/cgi-bin/user/info?access_token={0}&openid={1}&lang=zh_CN", access_token, openid);
WebRequest requestUserInfo = System.Net.WebRequest.Create(key);
WebResponse responseUser = requestUserInfo.GetResponse();weixinUserInfo = new StreamReader(responseUser.GetResponseStream()).ReadToEnd();
AppLog.Write("Get_unionid(unionid)返回信息:" + weixinUserInfo, LogMessageType.Info);}
catch (Exception ex)
{
AppLog.Write("获取会员信息:Get_unionid" + ex.Message, LogMessageType.Error);
}
return weixinUserInfo;
}
//第五步:根据获取的openid 与 unionid值,获取用户信息
就是用户之前绑定的用户信息表中去查询,一般有一张表,关联用户账号或者手机号码,有 openid 跟unionid信息。直接查询到用户信息即可。
第六步:
总结前面的业务,对外的api接口如下:
/// <summary>
///1.1 根据微信Code自动登录 获取会员信息
/// </summary>
/// <returns></returns>
[HttpGet]
[Route("WXAouthLogin")]
public IActionResult WXAouthLogin([FromQuery] MessageRequst requst)
{ResultResponse baseResult = new ResultResponse();
try
{
if (string.IsNullOrEmpty(requst.Code))
{
return Json(new { Result = false, Message = "参数不能为空!" });
}
//第一步 :根据Code 获取到 openid
string weiPayOpenidModelJsonStr = OAuthInfo.access_token(requst.Code);
AppLog.Write("微信服务号授权登录通过Code获取access_token返回信息:" + weiPayOpenidModelJsonStr, LogMessageType.Info);
WXOpenidModel resultModel = JsonConvert.DeserializeObject<WXOpenidModel>(weiPayOpenidModelJsonStr);//第二步: WXOpenidModel获取到的access_token的作用域是snsapi_base,获取不到unionId
// 应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息)
// 根据获取的openid获取unionId
// 从接口获取
M665WeChatGetTokenResult result = OAuthInfo.GetWeChatAccessToken().Result;
AppLog.Write("接口返回的access_token" + JsonConvert.SerializeObject(result), LogMessageType.Info);if (result == null)
{
AppLog.Write(String.Format("获取微信access_token错误"), LogMessageType.Info);
return Json(new { Result = false, Message = "获取access_token失败!" });
}
//第三步: 根据openid与access_token 获取unionid
string weixinUserInfo = OAuthInfo.Get_unionid(result.access_token, resultModel.openid);
AppLog.Write("WXAouthLogin微信服务号获取用户信息(unionid)返回信息:" + weixinUserInfo, LogMessageType.Info);
WXUserInfoModel wXUserInfo = JsonConvert.DeserializeObject<WXUserInfoModel>(weixinUserInfo);//第四步:根据获取的openid 与 unionid值,获取用户信息
UserInfoSmall uis = OAuthInfo.GetUserByWXOpenid(resultModel.openid, wXUserInfo.unionid);
if (uis == null)
{
return Json(new { Result = false, Message = "微信未绑定" });
}
else
{
return Json(new { Result = true, Data = uis });
}}
catch (Exception ex)
{
baseResult.State = false;
baseResult.Message = ex.Message;
}
AppLog.Write("获取会员信息:WXAouthLogin" + baseResult.Message, LogMessageType.Error);
return Json(baseResult);
}
}