参考文档
微信网页授权登陆的过程官方文档:
https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842
微信登陆过程简述:
OAuth认证,分成四步过程。
1.获取动态验证码Token
2.拿着自己应用的私钥(AppSecret)去获取访问令牌(access_token)
3.刷新token
4.获取用户信息(头像,appID)
注意事项:
1.将自己的域名不带网络协议的比如(www.qq.com)填写到文档说明的位置。
2.将微信授予你的文本文件放到Tomcat Root目录下
代码实现部分:
我认为这是一个模板代码,所以做成了插件,所以希望送给有缘人!
因为不难,所以先说实现吧:
授权登陆时通过与腾讯服务器之间交换JSON数据实现的,所以我用的是Jackson.
首先是令牌对象,用在第二步和第三步
@JsonIgnoreProperties(ignoreUnknown = true)
public class CodeForAccessToken {
/**
*
* 获取code后,请求以下链接获取access_token:
* https://api.weixin.qq.com/sns/oauth2/access_token?
* appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
* **/
/**
*
* 获取第二步的refresh_token后,请求以下链接获取access_token:
https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN
*
* **/
public CodeForAccessToken() {
super();
}
//JSON对象,第一步JSON对象和第二次JSON对象相同
/*
* { "access_token":"ACCESS_TOKEN",
"expires_in":7200,
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID",
"scope":"SCOPE" }
*
* **/
private String access_token;
private int expires_in;
private String refresh_token;
private String openid;
private String scope;
public String getAccess_token() {
return access_token;
}
public void setAccess_token(String access_token) {
this.access_token = access_token;
}
public int getExpires_in() {
return expires_in;
}
public void setExpires_in(int expires_in) {
this.expires_in = expires_in;
}
public String getRefresh_token() {
return refresh_token;
}
public void setRefresh_token(String refresh_token) {
this.refresh_token = refresh_token;
}
public String getOpenid() {
return openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
@Override
public String toString() {
return "CodeForAccessToken [\naccess_token=" + access_token +
", \n expires_in=" + expires_in +
", \n refresh_token="+ refresh_token +
", \n openid=" + openid +
", \n scope=" + scope + "]";
}
}
UserInfo对象-第四步要用
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
//这个属性能够放宽JSON转换政策,见Jackson API
@JsonIgnoreProperties(ignoreUnknown = true)
public class UserInfo {
public UserInfo() {
super();
}
/**
* { "openid":"OPENID",
"nickname":NICKNAME,
"sex":"1",
"province":"PROVINCE"
"city":"CITY",
"country":"COUNTRY",
"headimgurl": "http://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46",
"privilege":["PRIVILEGE1" "PRIVILEGE2" ],
"unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
}
*
*
*
* **/
private String openid;
private String nickname;
private String sex;
private String province;
private String city;
private String country;
private String headimgurl;
private String[] privilege;
private String unionid;
public String getOpenid() {
return openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getHeadimgurl() {
return headimgurl;
}
public void setHeadimgurl(String headimgurl) {
this.headimgurl = headimgurl;
}
public String[] getPrivilege() {
return privilege;
}
public void setPrivilege(String[] privilege) {
this.privilege = privilege;
}
public String getUnionid() {
return unionid;
}
public void setUnionid(String unionid) {
this.unionid = unionid;
}
@Override
public String toString() {
return "UserInfo [\n openid=" + openid
+ ", \n nickname=" + nickname
+ ", \n sex=" + sex
+ ", \n province=" + province
+ ", \n city=" + city
+ ", \n country=" + country
+ ", \n headimgurl=" + headimgurl
+ ", \n privilege="
+ Arrays.toString(privilege)
+ ", unionid=" + unionid + "]";
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
需要设置的对象
WeChatAPP对象其实封装了你的应用的一些信息
public class WechatAPP {
//微信接口的一些固有属性
//APPID
private static String APP_ID="xxxxx";
private static String APPURL="你打包后的war名";
//APPSecret
private static String SECRET="私钥";
private static String DOMAIN="https://www.qq.com/";
public static String getAPP_ID() {
return APP_ID;
}
public static String getSECRET() {
return SECRET;
}
public static String getDOMAIN() {
return DOMAIN;
}
static String startInAuthCodeGenerator(String code) {
/**
*
* https://api.weixin.qq.com/sns/oauth2/access_token?
* appid=APPID
* &secret=SECRET
* &code=CODE
* &grant_type=authorization_code
**/
String prepareURL="https://api.weixin.qq.com/sns/oauth2/access_token?"
+"appid="+WechatAPP.getAPP_ID()
+"&"+"secret="+WechatAPP.getSECRET()
+"&code="+code
+"&grant_type=authorization_code";
return prepareURL;
}
/**
* @see
* https://api.weixin.qq.com/sns/oauth2/refresh_token?
* appid=APPID
* &grant_type=refresh_token
* &refresh_token=REFRESH_TOKEN
*
* @return 微信授权登陆刷新access_token后的网址,没有经过编码
* **/
static String refreshInAuth(String token) {
String prepareURL="https://api.weixin.qq.com/sns/oauth2/refresh_token?"
+"appid="+APP_ID
+"&grant_type=refresh_token"
+"&refresh_token="+token;
return prepareURL;
}
/**
* @author onesl
* @Param
* openid和access_token
* @return
* 返回获取用户信息的链接,未经编码
*
* @see
* https://api.weixin.qq.com/sns/userinfo?
* access_token=ACCESS_TOKEN
* &openid=OPENID
* &lang=zh_CN
***/
static String InfoInAuth(String openid,String token){
String prepareURL="https://api.weixin.qq.com/sns/userinfo?"
+"access_token="+token
+"&openid="+openid
+"&lang=zh_CN";
return prepareURL;
}
static String encodeValue(String value) {
try {
return URLEncoder.encode(value, StandardCharsets.UTF_8.toString());
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return value;
}
public static String getAPPURL() {
return APPURL;
}
public static void setAPPURL(String aPPURL) {
APPURL = aPPURL;
}
}
一切准备妥当!你现在可以调用封装好的API了!
write a Controller
@Controller
public class WechatController {
private static final Logger logger=Logger.getLogger(WechatExplicitController.class);
@Autowired
CustomerRepository customerRepository;
@RequestMapping(path="/login")
public String loginEntry(@RequestParam("code") String code,
@RequestParam("state") String state,
HttpSession session) {
if(code.isEmpty()) {
return "error";
}
String readyURL=WechatAPP.startInAuthCodeGenerator(code);
ObjectMapper mapper=new ObjectMapper();
try {
/**第二步获取access_token*/
URL url=new URL(readyURL);
CodeForAccessToken token=mapper.readValue(url,CodeForAccessToken.class);
if(token==null) {return "error";}
if(token.getOpenid()==null) {return "error";}
/**第三步,刷新Access_token*/
readyURL=WechatAPP.refreshInAuth(token.getRefresh_token());
URL urlInRefresh=new URL(readyURL);
token=mapper.readValue(urlInRefresh,CodeForAccessToken.class);
if(token==null) {return "error";}
if(token.getOpenid()==null) { return "error";}
/**第四步:通过Access_token返回用户的全部信息*/
readyURL=WechatAPP.InfoInAuth(token.getOpenid(), token.getAccess_token());
URL infoURL=new URL(readyURL);
/**======================这一步你获取了用户的全部公开信息=======================*/
UserInfo userInfo=mapper.readValue(infoURL,UserInfo.class);
/**======================这一步你获取了用户的全部公开信息=======================*/
if(userInfo==null) {return "error"; }
if(userInfo.getOpenid()==null) {return "error";}
/**存储Session*/
session.setAttribute("id",customer.getId());
return "redirect:/index";
}
}
怎样使用这个模板?
修改WeChatAPP,填写相应的字段,如果上面的东西你都做了,你可以最终在控制器中获取到用户信息。得到了UserInfo对象了,目的不就达到了?哈哈。为了代码简洁我把异常处理的代码扔掉了,try几下,you’re ready to go!