100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > js 公众号 获取code_微信公众号开发之网页授权登录及code been used 解决!

js 公众号 获取code_微信公众号开发之网页授权登录及code been used 解决!

时间:2021-02-14 01:31:32

相关推荐

js 公众号 获取code_微信公众号开发之网页授权登录及code been  used 解决!

首先微信公众号开发网页授权登录使用环境:

开发工具:eclipse;服务器:tomcat8,开发语言:JAVA。

我写的网页授权登录时用开发者模式自定义view类型按钮点击跳转链接的。

微信网页授权登录首先以官方微信开发文档为准,大体共分为4步:

先说第一步获取code:

code说明:code作为换取access_token的票据,每次用户授权带上的code将不一样,code只能使用一次,5扽这未被使用自动过期。

微信公众开发文档给的有获取code的链接,建议直接复制来用,然后替换其中相应的参数即可。

链接为:

https://open./connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect其中参数说明:

这官网上都有,这里展示是想说明一下scope参数,请注意看官网上给出的demo:

请注意微信授权登录scope两种redirect_url后面跟的链接使用的协议。

这个协议使用不当可能会在项目部署到服务器上测试时在安卓和ios上出现问题。

至此,以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页的。用户感知的就是直接进入了回调页(往往是业务页面);

以snsapi_userinfo为scope发起的网页授权,是用来获取用户的基本信息的。但这种授权需要用户手动同意,并且由于用户同意过,所以无须关注,就可在授权后获取该用户的基本信息。

参数替换完毕如果以snsapi_userinfo为scope发起的网页授权,是在PC端点击菜单会跳出提示用户同意授权登录,如果用户未关注公众号时同样也会提示,示例页面:

如果是在移动端用户关注情况下则不会出现此页面。

如果用户同意授权,页面将跳转至 redirect_uri/?code=CODE&state=STATE,若跳转错误请根据日志输出的错误码在官网上查看相应的说明,附上官网上错误返回码说明:

然后是第二步根据链接传过来的code去获取网页授权access_token:

官网上给出的链接:

https://api./sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

这个access_token和基本的access_token不同,具体请参考官网说明,这里给出获取网页授权access_token的JAVA实现方法:

1 /**

2 * 获取网页授权凭证3 *4 *@paramappId 公众账号的唯一标识5 *@paramappSecret 公众账号的密钥6 *@paramcode7 *@returnWeixinAouth2Token8 */

9 public staticWeixinOauth2Token getOauth2AccessToken(String appId, String appSecret, String code) {10 WeixinOauth2Token wat = null;11 //拼接请求地址

12 String requestUrl = "https://api./sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";13 requestUrl = requestUrl.replace("APPID", appId);14 requestUrl = requestUrl.replace("SECRET", appSecret);15 requestUrl = requestUrl.replace("CODE", code);16 //获取网页授权凭证

17 JSONObject jsonObject = CommonUtil.httpsRequest(requestUrl, "GET", null);18 if (null !=jsonObject) {19 try{20 wat = newWeixinOauth2Token();21 wat.setAccessToken(jsonObject.getString("access_token"));22 wat.setExpiresIn(jsonObject.getInt("expires_in"));23 wat.setRefreshToken(jsonObject.getString("refresh_token"));24 wat.setOpenId(jsonObject.getString("openid"));25 wat.setScope(jsonObject.getString("scope"));26 } catch(Exception e) {27 wat = null;28 int errorCode = jsonObject.getInt("errcode");29 String errorMsg = jsonObject.getString("errmsg");30 log.error("获取网页授权凭证失败 errcode:{} errmsg:{}", errorCode, errorMsg);31 }32 }33 returnwat;34 }

需要的参数为开发者ID(AppID),开发者密码(AppSecret),和获取到的code。正确返回json数据包为:

然后第三步,如果需要的话进行,方法和第二步类似,所需链接官网给的有。

最后一步是获取用户的信息(需要scope为snsapi_userinfo,snsapi_base只能获取到用户的openId):

所需要的请求方法:

http:GET(请使用https协议) https://api./sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN

然后替换成相应的参数,JAVA代码为:

1 /**

2 * 通过网页授权获取用户信息3 *4 *@paramaccessToken 网页授权接口调用凭证5 *@paramopenId 用户标识6 *@returnSNSUserInfo7 */

8 public staticSNSUserInfo getSNSUserInfo(String accessToken, String openId) {9 SNSUserInfo snsUserInfo = null;10 //拼接请求地址

11 String requestUrl = "https://api./sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";12 requestUrl = requestUrl.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openId);13 //通过网页授权获取用户信息

14 JSONObject jsonObject = CommonUtil.httpsRequest(requestUrl, "GET", null);15

16 if (null !=jsonObject) {17 try{18 snsUserInfo = newSNSUserInfo();19 //用户的标识

20 snsUserInfo.setOpenId(jsonObject.getString("openid"));21 //昵称

22 snsUserInfo.setNickname(jsonObject.getString("nickname"));23 //性别(1是男性,2是女性,0是未知)

24 snsUserInfo.setSex(jsonObject.getInt("sex"));25 //用户所在国家

26 snsUserInfo.setCountry(jsonObject.getString("country"));27 //用户所在省份

28 snsUserInfo.setProvince(jsonObject.getString("province"));29 //用户所在城市

30 snsUserInfo.setCity(jsonObject.getString("city"));31 //用户头像

32 snsUserInfo.setHeadImgUrl(jsonObject.getString("headimgurl"));33 } catch(Exception e) {34 snsUserInfo = null;35 int errorCode = jsonObject.getInt("errcode");36 String errorMsg = jsonObject.getString("errmsg");37 log.error("获取用户信息失败 errcode:{} errmsg:{}", errorCode, errorMsg);38 }39 }40 returnsnsUserInfo;41 }

上面所述皆是根据微信公众号官网以及百度所写。另外还参考一篇很不错的微信公众号开发文档,可以说是带我入的门,给个链接:

下面说一下微信网页授权登录中遇到的code been used问题:

我在微信网页授权登录写完之后开始测试,在保证代码的正确性与准确性后,打开微信公众号,点击自己定义跳转链接的菜单,并成功进入,但是在点击刷新或者回退是会报错,错误的信息就是code been used。

官网上给出的说明很详细,code只能被使用一次,如果显示code been used则说明code被重复使用了。

首先说一个简单的code been used错误的产生:

有的开发者在写网页授权登录时会出现这样的页面:

这是在微信开发公众号上没有配置安全域名,导致微信网页授权登录时会显示这样的页面,url跳转了两次,传入的code被重复使用了,遇到这种的可以现在微信开发公众号里面配置安全域名。

然后说普遍遇到的code been used问题。

基本思路时:当我点击菜单按钮进入页面时,先去sssion缓存中去那由code获取到的openId,如果openId不存在,则证明code为首次使用,可以根据传过来的code获取相应的access_token和openId。

如果存在,则直接使用获取到的openId去获取用户的一系列信息。

我用的时springMVC,简单实现代码为:

首先在开发者定义的菜单路径上配置域名和跳转的控制器方法:

前面模糊的是自己配置的域名,后面/weixin/redirect则是要跳转的方法。

跳转到的方法为:

JAVA代码:

1 /**获取用户openId2 *@throwsIOException*/

3 @RequestMapping(value = "/redirect", method =RequestMethod.GET)4 public ModelAndView repairs(ModelAndView mav, HttpServletRequest request, HttpServletResponse resp) throwsIOException{5 String openId = (String) request.getSession().getAttribute("openId");//先从缓存中获取通过code得到的openID6 System.out.println(openId);//测试输出openId7 if(openId==null){//判断openId是否为空(判断code是否为第一次被使用)8 RedirectUtils.redireUrl1(request, resp);//openid为空也就是code被第一次使用时跳转方法9 return null;10 }11 mav.addObject("openId",openId);//没有被使用时12 mav.setViewName("/weixin/repairs");//返回要跳转的视图页面13 returnmav;14 }

RedirectUtils.redireUrl1(request, resp);为重定向跳转的路径。JAVA代码:

1 public static voidredireUrl1(HttpServletRequest request,HttpServletResponse response){2 System.out.println("跳转");//测试是否跳转过来了3 String a="";4 if(request.getQueryString()!=null){5 a="?"+request.getQueryString();6 }7 String url = Base64.getBase64(request.getRequestURL()+a);//此为链接中带的一些参数 不需要可以不用写8 System.out.println(request.getRequestURL()+a);9 String basePath = WeChatConfig.URL+"weixin/wxyz?url="+url;//redirect_uri地址10 System.out.println(basePath);11 String urls="https://open./connect/oauth2/authorize?appid=" + WeChatConfig.APP_ID+

12 "&redirect_uri=" + CommonUtil.urlEncodeUTF8(basePath)+

13 "&response_type=code" +

14 "&scope=snsapi_userinfo" +

15 "&state=STATE#wechat_redirect";16 try{17 response.sendRedirect(urls);//重定向执行url18 }catch(Exception e){19 e.printStackTrace();20 }21 }

其中Base64.getBase64为Base64加密方法,WeChatConfig.URL为你自己微信公众平台配置的安全域名,CommUtil.urlEncodeUTF8对重定向链接进行编码。

提供一下Base64方法中的加密解密方法,请先下载相应的jar包:

1 **

2 * Base64工具 CREATE .12.14form yjf3 *

4 */

5 public classBase64 {6 /**

7 * Base64加密8 *9 */

10 @SuppressWarnings("restriction")11 public staticString getBase64(String value) {12 byte[] bytes = null;13 String basevalue = null;14 try{15 bytes = value.getBytes("utf-8");16 } catch(UnsupportedEncodingException e) {17 e.printStackTrace();18 }19 if (bytes != null) {20 basevalue = newBASE64Encoder().encode(bytes);21 }22 returnbasevalue;23 }24

25 /**

26 * Base64解密27 *28 */

29 @SuppressWarnings("restriction")30 public staticString getFromBase64(String basevalue) {31 byte[] bytes = null;32 String result = null;33 if (basevalue != null) {34 BASE64Decoder decoder = newBASE64Decoder();35 try{36 bytes =decoder.decodeBuffer(basevalue);37 result = new String(bytes, "utf-8");38 } catch(Exception e) {39 e.printStackTrace();40 }41 }42 returnresult;43 }44

45 }

然后时CommUtil.urlEncodeUTF8编码代码:

1 /**

2 * URL编码(utf-8)3 *4 *@paramsource5 *@return

6 */

7 public staticString urlEncodeUTF8(String source) {8 String result =source;9 try{10 result = .URLEncoder.encode(source, "utf-8");11 } catch(UnsupportedEncodingException e) {12 e.printStackTrace();13 }14 returnresult;15 }

然后方法执行response.sendRedirect(urls);跳转回wxyz方法进行获取一系列参数,代码为:

1 @RequestMapping(value="/wxyz",method=RequestMethod.GET)2 publicModelAndView wxYz(ModelAndView mvc,HttpServletRequest req,HttpServletResponse response){3 System.out.println("微信验证");//测试是否跳转到此方法中4 String code=req.getParameter("code");//获取url参数中的code5 WeixinOauth2Token weixinOauth2Token =AdvancedUtil.getOauth2AccessToken(WeChatConfig.APP_ID, WeChatConfig.APP_SECRET, code);6 if(weixinOauth2Token.getOpenId()!=null){7 String openId =weixinOauth2Token.getOpenId();8 req.getSession().setAttribute("openId",openId);//将获取到的openID存入session缓存中9 System.out.println("openId"+openId);10 mvc.addObject("openId",openId);11 mvc.setViewName("redirect:/weixin/wxLogin");12 returnmvc;13 }14 return null;15 }

其中AdvancedUtil.getOauth2AccessToken方法时获取网页授权access_token 方法,代码为:

1 /**

2 * 获取网页授权凭证3 *4 *@paramappId 公众账号的唯一标识5 *@paramappSecret 公众账号的密钥6 *@paramcode7 *@returnWeixinAouth2Token8 */

9 public staticWeixinOauth2Token getOauth2AccessToken(String appId, String appSecret, String code) {10 WeixinOauth2Token wat = null;11 //拼接请求地址

12 String requestUrl = "https://api./sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";13 requestUrl = requestUrl.replace("APPID", appId);14 requestUrl = requestUrl.replace("SECRET", appSecret);15 requestUrl = requestUrl.replace("CODE", code);16 //获取网页授权凭证

17 JSONObject jsonObject = CommonUtil.httpsRequest(requestUrl, "GET", null);18 if (null !=jsonObject) {19 try{20 wat = newWeixinOauth2Token();21 wat.setAccessToken(jsonObject.getString("access_token"));22 wat.setExpiresIn(jsonObject.getInt("expires_in"));23 wat.setRefreshToken(jsonObject.getString("refresh_token"));24 wat.setOpenId(jsonObject.getString("openid"));25 wat.setScope(jsonObject.getString("scope"));26 } catch(Exception e) {27 wat = null;28 int errorCode = jsonObject.getInt("errcode");29 String errorMsg = jsonObject.getString("errmsg");30 log.error("获取网页授权凭证失败 errcode:{} errmsg:{}", errorCode, errorMsg);31 }32 }33 returnwat;34 }

使用此方法替换上相应的参数即可。因为微信授权登录会跳转两次链接,所以当获取成功则跳转到wxLogin方法中进行验证:

1 String bassPath1 = WeChatConfig.URL+"weixin/wxyz";//定义的路径2 @RequestMapping(value="wxLogin1",method=RequestMethod.GET)3 publicModelAndView wxLogin(HttpServletRequest request,HttpServletResponse response){4 String openId = (String) request.getSession().getAttribute("openId");//先从缓存中去拿openId5

6 if(openId==null){//如果没有的话7 String url="https://open./connect/oauth2/authorize?appid=" + WeChatConfig.APP_ID +

8 "&redirect_uri=" + CommonUtil.urlEncodeUTF8(bassPath1)+

9 "&response_type=code" +

10 "&scope=snsapi_userinfo" +

11 "&state=STATE#wechat_redirect";12 try{13 response.sendRedirect(url);14 } catch(IOException e) {15 e.printStackTrace();16 }17

18 }else{19

20 return new ModelAndView("weixin/repairs");//返回页面21 }22 return null;23 }

至此,打开所需要的页面,无论时第一次进入还是刷新 都不会出现code been used这种情况了,至少本人测试没有出现过。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。