[JAVA实现]微信公众号网页授权登录 您所在的位置:网站首页 微信公众号怎样授权登录 [JAVA实现]微信公众号网页授权登录

[JAVA实现]微信公众号网页授权登录

2024-07-13 17:09| 来源: 网络整理| 查看: 265

网上搜资料时,网友都说官方文档太垃圾了不易看懂,如何如何的。现在个人整理了一个通俗易懂易上手的,希望可以帮助到刚接触微信接口的你。

请看流程图!看懂图,就懂了一半了:

其实整体流程大体只需三步:用户点击登录按钮(其实就相当于一个链接) ---》  用户点击授权登录  ----》  实现获取用户信息代码。

然后获取用户信息代码只需三步:获取code  ----》 通过code获取access_token和openId  ---》 通过access_token和openId获取用户信息(包含union)。

 

以上便是整体套路,当然官网上也有,但具体如何实现呢?

不着急,咱们一步一步来!

 

第一步:微信登录按钮

它其实就是一个连接,不过想得到这个链接,有一点点麻烦。

1、设置。 微信公众平台---》接口权限---》网页授权---》修改 ---》设置网页授权域名(域名,不含http://),其实就是微信调你的java方法的项目路径或项目域名,如:www.zzff.net/pp ---》点击设置后弹出页面(大致意思,将MP_verify_31qRIDcjN8ZD1lVJ.txt放在你项目路径下面,如:www.ffzz.net/pp/MP_verify_31qRIDcjN8ZD1lVJ.txt 能访问到) ---》点击确认,授权回调页面域名设置成功!

2、拼链接。   https://open.weixin.qq.com/connect/oauth2/authorize?appid=xxx公众号IDxxxxx   &  redirect_uri = 授权回调页面域名/你的action(即微信授权后跳向的地址)

& response_type=code(固定的) & scope = snsapi_userinfo(或者snsapi_base默认授权)  & state=STATE#wechat_redirect

 如:https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxf0e81c3bee622d60&redirect_uri=http%3A%2F%2Fnba.bluewebgame.com%2Foauth_response.php&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect

这个链接中参数的具体含义,官方解释如下:

参数是否必须说明 appid 是 公众号的唯一标识 redirect_uri 是 授权后重定向的回调链接地址,请使用urlencode对链接进行处理 response_type 是 返回类型,请填写code scope 是 应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息) state 否 重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节  #wechat_redirect 是 无论直接打开还是做页面302重定向时候,必须带此参数

 

第二步:授权确认登录 

这一步最简单,第一步登录链接拼好后,在手机微信中打开,微信便会跳转到确认授权页面,点击确认授权即可。(这一步,不用开发者做处理!)

 

第三步:获取用户信息 (重点)这一步便是真正的代码实现的地方。开篇便讲了,它只需三步:获取code  ----》 通过code获取access_token和openId  ---》 通过access_token和openId获取用户信息。

First:   获取code

Second:  获取网页授权access_token和openId  

Third:通过access_token和openId获取用户信息。

关于union机制的细节:如果开发者需要公众号微信登录和APP微信登录共用一个微信ID,那个就需要union机制了。其实很简单,只需在微信开放平台(open.weixin.qq.com)绑定公众号,获取用户信息时就会返回union字段。

 

具体代码实现为:实体 ----  方法  --- 工具

实体Oauth2Token:

1 package com.wfcm.wxUitls; 2 3 /** 4 * 类名: WeixinOauth2Token 5 * 描述: 网页授权信息 6 * 创建时间: 2015-11-27 7 * 发布版本:V1.0 8 */ 9 public class Oauth2Token { 10 // 网页授权接口调用凭证 11 private String accessToken; 12 // 凭证有效时长 13 private int expiresIn; 14 // 用于刷新凭证 15 private String refreshToken; 16 // 用户标识 17 private String openId; 18 // 用户授权作用域 19 private String scope; 20 21 public String getAccessToken() { 22 return accessToken; 23 } 24 25 public void setAccessToken(String accessToken) { 26 this.accessToken = accessToken; 27 } 28 29 public int getExpiresIn() { 30 return expiresIn; 31 } 32 33 public void setExpiresIn(int expiresIn) { 34 this.expiresIn = expiresIn; 35 } 36 37 public String getRefreshToken() { 38 return refreshToken; 39 } 40 41 public void setRefreshToken(String refreshToken) { 42 this.refreshToken = refreshToken; 43 } 44 45 public String getOpenId() { 46 return openId; 47 } 48 49 public void setOpenId(String openId) { 50 this.openId = openId; 51 } 52 53 public String getScope() { 54 return scope; 55 } 56 57 public void setScope(String scope) { 58 this.scope = scope; 59 } 60 } View Code

实体SNSUserInfo:

1 package com.wfcm.wxUitls; 2 3 import java.util.List; 4 5 /** 6 * 类名: SNSUserInfo 7 * 描述: 通过网页授权获取的用户信息 8 * 开发人员: wzf 9 * 创建时间: 2015-11-27 10 * 发布版本:V1.0 11 */ 12 public class SNSUserInfo { 13 // 用户标识 14 private String openId; 15 // 用户昵称 16 private String nickname; 17 // 性别(1是男性,2是女性,0是未知) 18 private int sex; 19 // 国家 20 private String country; 21 // 省份 22 private String province; 23 // 城市 24 private String city; 25 // 用户头像链接 26 private String headImgUrl; 27 // 用户特权信息 28 private List privilegeList; 29 30 private String unionid; 31 32 public String getUnionid() { 33 return unionid; 34 } 35 36 public void setUnionid(String unionid) { 37 this.unionid = unionid; 38 } 39 40 public String getOpenId() { 41 return openId; 42 } 43 44 public void setOpenId(String openId) { 45 this.openId = openId; 46 } 47 48 public String getNickname() { 49 return nickname; 50 } 51 52 public void setNickname(String nickname) { 53 this.nickname = nickname; 54 } 55 56 public int getSex() { 57 return sex; 58 } 59 60 public void setSex(int sex) { 61 this.sex = sex; 62 } 63 64 public String getCountry() { 65 return country; 66 } 67 68 public void setCountry(String country) { 69 this.country = country; 70 } 71 72 public String getProvince() { 73 return province; 74 } 75 76 public void setProvince(String province) { 77 this.province = province; 78 } 79 80 public String getCity() { 81 return city; 82 } 83 84 public void setCity(String city) { 85 this.city = city; 86 } 87 88 public String getHeadImgUrl() { 89 return headImgUrl; 90 } 91 92 public void setHeadImgUrl(String headImgUrl) { 93 this.headImgUrl = headImgUrl; 94 } 95 96 public List getPrivilegeList() { 97 return privilegeList; 98 } 99 100 public void setPrivilegeList(List privilegeList) { 101 this.privilegeList = privilegeList; 102 } 103 } View Code

方法WxController(其中authorize() 方法就是请求第一步获取的链接):

1 package com.wfcm.controller; 2 3 import java.io.BufferedReader; 4 import java.io.IOException; 5 import java.io.InputStreamReader; 6 import java.io.UnsupportedEncodingException; 7 import java.net.URL; 8 import java.net.URLConnection; 9 import java.net.URLEncoder; 10 import java.security.MessageDigest; 11 import java.security.NoSuchAlgorithmException; 12 import java.util.ArrayList; 13 import java.util.Formatter; 14 import java.util.HashMap; 15 import java.util.List; 16 import java.util.Map; 17 import java.util.UUID; 18 19 import javax.servlet.http.HttpServletRequest; 20 import javax.servlet.http.HttpServletResponse; 21 22 import org.apache.http.client.utils.URLEncodedUtils; 23 import org.json.JSONObject; 24 import org.slf4j.Logger; 25 import org.slf4j.LoggerFactory; 26 import org.springframework.beans.factory.annotation.Autowired; 27 import org.springframework.stereotype.Controller; 28 import org.springframework.web.bind.annotation.RequestMapping; 29 import org.springframework.web.bind.annotation.ResponseBody; 30 31 import com.alibaba.fastjson.JSON; 32 import com.alibaba.fastjson.JSONArray; 33 import com.alibaba.fastjson.util.IOUtils; 34 import com.wfcm.annotation.IgnoreSign; 35 import com.wfcm.annotation.IgnoreToken; 36 import com.wfcm.entity.WfMemberEntity; 37 import com.wfcm.service.WfMemberService; 38 import com.wfcm.service.WfMemberSessionService; 39 import com.wfcm.utils.FastJSONUtils; 40 import com.wfcm.utils.NetUtil; 41 import com.wfcm.utils.R; 42 import com.wfcm.wxUitls.AccessToken; 43 import com.wfcm.wxUitls.JsapiTicket; 44 import com.wfcm.wxUitls.Oauth2Token; 45 import com.wfcm.wxUitls.SNSUserInfo; 46 47 @Controller 48 @RequestMapping("/wx") 49 @ResponseBody 50 public class WxController { 51 52 private static Logger log = LoggerFactory.getLogger(WxController.class); 53 54 55 /** 56 * 向指定URL发送GET方法的请求 57 * 58 * @param url 59 * 发送请求的URL 60 * @param param 61 * 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 62 * @return URL 所代表远程资源的响应结果 63 * 64 * 用户同意授权,获取code 65 */ 66 @RequestMapping("/authorize") 67 @ResponseBody 68 @IgnoreToken 69 public static R authorize() { 70 String appid = "wxbb000000000e"; 71 //String uri ="wftest.zzff.net/wx/weixinLogin"; 72 String uri = urlEncodeUTF8("wftest.zzff.net/api/wx/weixinLogin"); 73 String result = ""; 74 BufferedReader in = null; 75 try { 76 String urlNameString = "https://open.weixin.qq.com/connect/oauth2/authorize?appid="+appid+"&redirect_uri="+uri+"&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect"; 77 78 URL realUrl = new URL(urlNameString); 79 // 打开和URL之间的连接 80 URLConnection connection = realUrl.openConnection(); 81 // 设置通用的请求属性 82 connection.setRequestProperty("accept", "*/*"); 83 connection.setRequestProperty("connection", "Keep-Alive"); 84 connection.setRequestProperty("user-agent", 85 "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); 86 // 建立实际的连接 87 connection.connect(); 88 // 获取所有响应头字段 89 Map map = connection.getHeaderFields(); 90 // 遍历所有的响应头字段 91 for (String key : map.keySet()) { 92 System.out.println(key + "--->" + map.get(key)); 93 } 94 // 定义 BufferedReader输入流来读取URL的响应 95 in = new BufferedReader(new InputStreamReader( 96 connection.getInputStream())); 97 String line =null; 98 while ((line = in.readLine()) != null) { 99 result += line; 100 } 101 /* com.alibaba.fastjson.JSONObject jsonObj= FastJSONUtils.getJSONObject(result); 102 String access_token = jsonObj.getString("access_token"); 103 long expires_in = Long.valueOf(jsonObj.getString("expires_in")); 104 */ 105 } catch (Exception e) { 106 System.out.println("发送GET请求出现异常!" + e); 107 e.printStackTrace(); 108 } 109 // 使用finally块来关闭输入流 110 finally { 111 try { 112 if (in != null) { 113 in.close(); 114 } 115 } catch (Exception e2) { 116 e2.printStackTrace(); 117 } 118 } 119 return R.ok(result); 120 } 121 122 @RequestMapping("/weixinLogin") 123 @ResponseBody 124 @IgnoreToken 125 @IgnoreSign 126 public void weixinLogin(HttpServletRequest request,HttpServletResponse response) throws Exception { 127 // 用户同意授权后,能获取到code 128 Map params = request.getParameterMap();//针对get获取get参数 129 String[] codes = params.get("code");//拿到code的值 130 String code = codes[0];//code 131 //String[] states = params.get("state"); 132 //String state = states[0];//state 133 134 System.out.println("****************code:"+code); 135 // 用户同意授权 136 if (!"authdeny".equals(code)) { 137 // 获取网页授权access_token 138 Oauth2Token oauth2Token = getOauth2AccessToken("wxb0000000000e", "4c22222233333335555a9", code); 139 System.out.println("***********************************oauth2Token信息:"+oauth2Token.toString()); 140 // 网页授权接口访问凭证 141 String accessToken = oauth2Token.getAccessToken(); 142 // 用户标识 143 String openId = oauth2Token.getOpenId(); 144 // 获取用户信息 145 SNSUserInfo snsUserInfo = getSNSUserInfo(accessToken, openId); 146 System.out.println("***********************************用户信息unionId:"+snsUserInfo.getUnionid()+"***:"+snsUserInfo.getNickname()); 147 // 设置要传递的参数 148 149 //具体业务start 150 151 //具体业务end 152 153 String url = "http://wftest.zzff.net/#/biddd?from=login&tokenId="+snsUserInfo.getUnionid(); 154 155 response.sendRedirect(url); 156 return ; 157 } 158 } 159 160 161 /** 162 * 获取网页授权凭证 163 * 164 * @param appId 公众账号的唯一标识 165 * @param appSecret 公众账号的密钥 166 * @param code 167 * @return WeixinAouth2Token 168 */ 169 public static Oauth2Token getOauth2AccessToken(String appId, String appSecret, String code) { 170 Oauth2Token wat = null; 171 // 拼接请求地址 172 String requestUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code"; 173 requestUrl = requestUrl.replace("APPID", appId); 174 requestUrl = requestUrl.replace("SECRET", appSecret); 175 requestUrl = requestUrl.replace("CODE", code); 176 // 获取网页授权凭证 177 com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject(NetUtil.get(requestUrl)); 178 if (null != jsonObject) { 179 try { 180 wat = new Oauth2Token(); 181 wat.setAccessToken(jsonObject.getString("access_token")); 182 wat.setExpiresIn(jsonObject.getInteger("expires_in")); 183 wat.setRefreshToken(jsonObject.getString("refresh_token")); 184 wat.setOpenId(jsonObject.getString("openid")); 185 wat.setScope(jsonObject.getString("scope")); 186 } catch (Exception e) { 187 wat = null; 188 int errorCode = jsonObject.getInteger("errcode"); 189 String errorMsg = jsonObject.getString("errmsg"); 190 log.error("获取网页授权凭证失败 errcode:{} errmsg:{}", errorCode, errorMsg); 191 } 192 } 193 return wat; 194 } 195 196 /** 197 * 通过网页授权获取用户信息 198 * 199 * @param accessToken 网页授权接口调用凭证 200 * @param openId 用户标识 201 * @return SNSUserInfo 202 */ 203 public static SNSUserInfo getSNSUserInfo(String accessToken, String openId) { 204 SNSUserInfo snsUserInfo = null; 205 // 拼接请求地址 206 String requestUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID"; 207 requestUrl = requestUrl.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openId); 208 // 通过网页授权获取用户信息 209 com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject(NetUtil.get(requestUrl)); 210 211 if (null != jsonObject) { 212 try { 213 snsUserInfo = new SNSUserInfo(); 214 // 用户的标识 215 snsUserInfo.setOpenId(jsonObject.getString("openid")); 216 // 昵称 217 snsUserInfo.setNickname(jsonObject.getString("nickname")); 218 // 性别(1是男性,2是女性,0是未知) 219 snsUserInfo.setSex(jsonObject.getInteger("sex")); 220 // 用户所在国家 221 snsUserInfo.setCountry(jsonObject.getString("country")); 222 // 用户所在省份 223 snsUserInfo.setProvince(jsonObject.getString("province")); 224 // 用户所在城市 225 snsUserInfo.setCity(jsonObject.getString("city")); 226 // 用户头像 227 snsUserInfo.setHeadImgUrl(jsonObject.getString("headimgurl")); 228 // 用户特权信息 229 List list = JSON.parseArray(jsonObject.getString("privilege"),String.class); 230 snsUserInfo.setPrivilegeList(list); 231 //与开放平台共用的唯一标识,只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。 232 snsUserInfo.setUnionid(jsonObject.getString("unionid")); 233 } catch (Exception e) { 234 snsUserInfo = null; 235 int errorCode = jsonObject.getInteger("errcode"); 236 String errorMsg = jsonObject.getString("errmsg"); 237 log.error("获取用户信息失败 errcode:{} errmsg:{}", errorCode, errorMsg); 238 } 239 } 240 return snsUserInfo; 241 } 242 243 /** 244 * URL编码(utf-8) 245 * 246 * @param source 247 * @return 248 */ 249 public static String urlEncodeUTF8(String source) { 250 String result = source; 251 try { 252 result = java.net.URLEncoder.encode(source, "utf-8"); 253 } catch (UnsupportedEncodingException e) { 254 e.printStackTrace(); 255 } 256 return result; 257 } 258 259 private static String byteToHex(final byte[] hash) { 260 Formatter formatter = new Formatter(); 261 for (byte b : hash) 262 { 263 formatter.format("%02x", b); 264 } 265 String result = formatter.toString(); 266 formatter.close(); 267 return result; 268 } 269 270 private static String create_nonce_str() { 271 return UUID.randomUUID().toString(); 272 } 273 274 private static String create_timestamp() { 275 return Long.toString(System.currentTimeMillis() / 1000); 276 } 277 } View Code

工具NetUtil:

1 package com.wfcm.utils; 2 3 import java.io.BufferedInputStream; 4 import java.io.IOException; 5 import java.io.InputStreamReader; 6 import java.io.UnsupportedEncodingException; 7 import java.util.ArrayList; 8 import java.util.Collection; 9 import java.util.List; 10 import java.util.Map; 11 12 import org.apache.commons.httpclient.NameValuePair; 13 import org.apache.http.HttpEntity; 14 import org.apache.http.HttpResponse; 15 import org.apache.http.client.entity.UrlEncodedFormEntity; 16 import org.apache.http.clienthods.HttpGet; 17 import org.apache.http.clienthods.HttpPost; 18 import org.apache.http.impl.client.CloseableHttpClient; 19 import org.apache.http.impl.client.HttpClientBuilder; 20 import org.apache.http.message.BasicNameValuePair; 21 22 /** 23 * Created by Song on 2016/11/28. 24 * 基于HttpClient提供网络访问工具 25 */ 26 public final class NetUtil { 27 public static CloseableHttpClient httpClient = HttpClientBuilder.create().build(); 28 29 /** 30 * get请求获取String类型数据 31 * @param url 请求链接 32 * @return 33 */ 34 public static String get(String url){ 35 StringBuffer sb = new StringBuffer(); 36 HttpGet httpGet = new HttpGet(url); 37 try { 38 HttpResponse response = httpClient.execute(httpGet); //1 39 40 HttpEntity entity = response.getEntity(); 41 InputStreamReader reader = new InputStreamReader(entity.getContent(),"utf-8"); 42 char [] charbufer; 43 while (0


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有