标题
微信开放平台文档
第一步:请求CODE
第三方使用网站应用授权登录前请注意已获取相应网页授权作用域(scope=snsapi_login),则可以通过在PC端打开以下链接: https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect 若提示“该链接无法访问”,请检查参数是否填写错误,如redirect_uri的域名与审核时填写的授权域名不一致或scope不为snsapi_login。
第二步:通过code获取access_token
通过code获取access_token
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
第三步:通过access_token调用接口
获取access_token后,进行接口调用,有以下前提:
- access_token有效且未超时;
- 微信用户已授权给第三方应用帐号相应接口作用域(scope)。
对于接口作用域(scope),能调用的接口有以下:
“urlencode编码:就是将字符串以URL编码,一种编码方式,主要为了解决url中中文乱码问题。
在线URL编码解码工具1
在线URL编码解码工具2
VendorsController
package cn.itrip.auth.controller;import cn.itrip.auth.exception.RedisException;import cn.itrip.auth.exception.TokenGenerateException;
import cn.itrip.auth.exception.TokenInvalidException;
import cn.itrip.auth.exception.TokenTimeProtectedException;
import cn.itrip.auth.service.token.TokenService;
import cn.itrip.auth.service.user.UserService;
import cn.itrip.beans.dto.Dto;
import cn.itrip.beans.pojo.ItripUser;
import cn.itrip.beans.vo.token.ItripTokenVO;
import cn.itrip.beans.vo.token.ItripWechatTokenVO;import cn.itrip.util.common.DtoUtil;
import cn.itrip.util.common.ErrorCode;
import cn.itrip.util.common.UrlUtils;
import com.alibaba.fastjson.JSON;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.ParseException;
import java.util.Date;
import java.util.Map;@Controller
@RequestMapping("/vendors")
public class VendorsController {@Resourceprivate UserService userService;@Resourceprivate TokenService tokenService;@RequestMapping(value = "/wechat/login")public void wechatLogin(HttpServletResponse response) throws Exception {System.out.println("--------------------------------------------hello");//网站应用的请求url itrip_auth_war 这里要跟你tomcat后加的啥
// String REDIRECT_URI = "http://localhost:8080/itrip_auth_war/vendors/wechat/callback";String REDIRECT_URI = "http://localhost:8080/auth/vendors/wechat/callback";//生成二维码的url
/* String codeUrl = "https://open.weixin.qq.com/connect/qrconnect" +"?appid=wxe1e368df55511ed7" +"&redirect_uri=https%3A%2F%2Fwww.itrip.com%2Flogin%2FwechatCallBack" +"&response_type=code&scope=snsapi_login" +"&state=bXVFRm9pdWJZQTAxOUI4MkIzRjM2NkM5MjgzOTExMUEzMUM2N0ZEQzVF#wechat_redirect";*/String codeUrl = "https://open.weixin.qq.com/connect/qrconnect" +"?appid=wx9168f76f000a0d4c" +"&redirect_uri=" + java.net.URLEncoder.encode(REDIRECT_URI, "utf-8") +"&response_type=code" +"&scope=snsapi_login" +"&state=STATE#wechat_redirect";//页面重定向response.sendRedirect(codeUrl);
//现在你去网页输入 http://localhost:8080/auth/vendors/wechat/login 就会出现微信扫码//然后用微信扫 他会跳转一个网址 404 把网址复制下来 用里面的跳转路径 写方法//HTTP状态404-/ auth / vendors / wechat / callback//http://localhost:8080/auth/vendors/wechat/callback?code=091RJEGa1Ly8yz0OMYFa16bKGz1RJEGu&state=STATE}@RequestMapping(value = "/wechat/callback", method = RequestMethod.GET)@ResponseBodypublic Dto wechatCallback(@RequestParam String code, @RequestParam String state,HttpServletRequest request, HttpServletResponse response) throws Exception {//获取code:cod为空的话表示用户拒绝使用微信登录if (code == null) {return DtoUtil.returnFail("用户未授权", ErrorCode.AUTH_AUTHENTICATION_FAILED);}//appid+secret+code换取accessTokenString accessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token" +"?appid=wx9168f76f000a0d4c" +"&secret=8ba69d5639242c3bd3a69dffe84336c1" +"&code=" + code +"&grant_type=authorization_code";String accessToken = UrlUtils.loadURL(accessTokenUrl);/*json格式:{"access_token":"ACCESS_TOKEN","expires_in":7200,"refresh_token":"REFRESH_TOKEN","openid":"OPENID","scope":"SCOPE","unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"}错误返回样例:
{
"errcode":40030,"errmsg":"invalid refresh_token"
}* */Map mapToken = JSON.parseObject(accessToken, Map.class);if (mapToken.get("errcode") != null) {return DtoUtil.returnFail("用户授权失败", ErrorCode.AUTH_AUTHENTICATION_FAILED);}//判断用户是否首次微信账户登录,如果是,创建用户信息ItripUser user = userService.findUserByUserCode(mapToken.get("openid").toString());if (user == null) {//创建新用户user = new ItripUser();//激活用户user.setActivated(1);//微信登录user.setUserType(1);//创建时间user.setCreationDate(new Date());//userCode:微信用户openid作为本地库用户名user.setUserCode(mapToken.get("openid").toString());//userNameuser.setUserName(mapToken.get("openid").toString());//注册用户userService.itripCreateUser(user);
// user = userService.findUserByUserCode(mapToken.get("openid").toString());}//本站点的token置换ItripTokenVO tokenVO = tokenService.generatorToken2(request.getHeader("user-agent"), user);//将token保存到redistokenService.saveToken(tokenVO.getToken(), user);//页面展示:从微信的二维码页面重定向过来,页面完全重新生成,跳转到应该指向的某个页面,随响应携带微信的token信息//response.sendRedirect ----> ……html:access_token=xxx&refresh_token=xxx&token=xxxItripWechatTokenVO wechatTokenVO = new ItripWechatTokenVO(tokenVO.getToken(), tokenVO.getExpTime(), tokenVO.getGenTime());wechatTokenVO.setAccessToken(mapToken.get("access_token").toString());wechatTokenVO.setExpiresIn(mapToken.get("expires_in").toString());wechatTokenVO.setOpenid(mapToken.get("openid").toString());wechatTokenVO.setRefreshToken(mapToken.get("refresh_token").toString());return DtoUtil.returnDataSuccess(wechatTokenVO);}
// 微信扫码后得到下面需要的参数 accessToken openid
//http://localhost:8080/auth/vendors/wechat/user/info?accessToken=36_YJN602dj1HenX3JjWYmHJoExRmJDG-J8I7wdNRwJM_NCBGnBK-HYZgvPavDf3VSKGTMHPRpbU0kh41eOUt-hEPHdbhDb_JHvZZJcVbWu-Pw&openid=oPxiwwnPak_hlYR0xqQFtxKX-SFQ
//http://localhost:8080/auth/vendors/wechat/user/info
// ?accessToken=
// 36_YJN602dj1HenX3JjWYmHJoExRmJDG-J8I7wdNRwJM_NCBGnBK-HYZgvPavDf3VSKGTMHPRpbU0kh41eOUt-hEPHdbhDb_JHvZZJcVbWu-Pw
// &openid=
// oPxiwwnPak_hlYR0xqQFtxKX-SFQ//http://localhost:8080/auth/vendors/wechat/user/info?accessToken=&openid=@RequestMapping(value = "/wechat/user/info", method = RequestMethod.GET)@ResponseBodypublic Dto getWechatUserInfo(@RequestParam String accessToken, @RequestParam String openid) throws Exception {try {String url = "https://api.weixin.qq.com/sns/userinfo" +"?access_token=" + accessToken +"&openid=" + openid;String userInfoJson = UrlUtils.loadURL(url);Map userInfo = JSON.parseObject(userInfoJson, Map.class);//查询用户ItripUser user = userService.findUserByUserCode(userInfo.get("openid").toString());//更新用户名user.setUserName(userInfo.get("nickname").toString());userService.updateItripUser(user);return DtoUtil.returnDataSuccess(userInfo);} catch (Exception e) {return DtoUtil.returnFail("加载微信用户信息失败", ErrorCode.AUTH_UNKNOWN);}}
//http://localhost:8080/auth/vendors/wechat/token/refresh@RequestMapping(value = "/wechat/token/refresh", method = RequestMethod.POST)@ResponseBodypublic Dto refreshWechatToken(HttpServletRequest request) throws Exception {//网站token置换(与之前的开发中相同)//request--->token user-agentString token = request.getHeader("token");String agent = request.getHeader("user-agent");String refreshToken = request.getHeader("refreshtoken");//调用业务方法完成token置换ItripTokenVO tokenVO = null;try {tokenVO = tokenService.replaceToken(agent, token);} catch (TokenInvalidException | ParseException e) {return DtoUtil.returnFail("token验证失败", ErrorCode.AUTH_TOKEN_INVALID);} catch (TokenTimeProtectedException e) {return DtoUtil.returnFail("token置换时间受保护", ErrorCode.AUTH_REPALCE_TIME_PROTECTED_FAILED);} catch (TokenGenerateException e) {return DtoUtil.returnFail("token创建失败", ErrorCode.AUTH_TOKEN_CREATE_FAILED);} catch (RedisException e) {return DtoUtil.returnFail("token保存失败", ErrorCode.AUTH_UNKNOWN);}//微信token置换(需要新实现的功能)String url = "https://api.weixin.qq.com/sns/oauth2/refresh_token" +"?appid=wx9168f76f000a0d4c" +"&grant_type=refresh_token" +"&refresh_token=" + refreshToken;String tokenJson = UrlUtils.loadURL(url);Map wechatToken = JSON.parseObject(tokenJson,Map.class);if(null!=wechatToken.get("errcode")){return DtoUtil.returnFail(wechatToken.get("微信token置换失败").toString(), ErrorCode.AUTH_REPLACEMENT_FAILED);}//返回ItripWechatTokenVO (整合了本地会话与微信会话)ItripWechatTokenVO wechatTokenVO = new ItripWechatTokenVO(tokenVO.getToken(), tokenVO.getExpTime(), tokenVO.getGenTime());wechatTokenVO.setAccessToken(wechatToken.get("access_token").toString());wechatTokenVO.setExpiresIn(wechatToken.get("expires_in").toString());wechatTokenVO.setOpenid(wechatToken.get("openid").toString());wechatTokenVO.setRefreshToken(wechatToken.get("refresh_token").toString());return DtoUtil.returnDataSuccess(wechatTokenVO);}}