微信浏览器调起微信登录
1.主要类
1.NetUtil类
package com.Ipwx;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* Created by Song on 2016/11/28.
* 基于HttpClient提供网络访问工具
*/
public final class NetUtil {
public static CloseableHttpClient httpClient = HttpClientBuilder.create().build();
/**
* get请求获取String类型数据
* @param url 请求链接
* @return
*/
public static String get(String url){
StringBuffer sb = new StringBuffer();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse response = httpClient.execute(httpGet); //1
HttpEntity entity = response.getEntity();
InputStreamReader reader = new InputStreamReader(entity.getContent(),"utf-8");
char [] charbufer;
while (0<reader.read(charbufer=new char[10])){
sb.append(charbufer);
}
}catch (IOException e){//1
e.printStackTrace();
}finally {
httpGet.releaseConnection();
}
return sb.toString();
}
/**
* post方式请求数据
* @param url 请求链接
* @param data post数据体
* @return
*/
@SuppressWarnings("unchecked")
public static String post(String url, Map<String,String> data){
StringBuffer sb = new StringBuffer();
HttpPost httpPost = new HttpPost(url);
List<NameValuePair> valuePairs = new ArrayList<NameValuePair>();
if(null != data) {
for (String key : data.keySet()) {
valuePairs.addAll((Collection<? extends NameValuePair>) new BasicNameValuePair(key, data.get(key)));
}
}
try {
httpPost.setEntity(new UrlEncodedFormEntity((List<? extends org.apache.http.NameValuePair>) valuePairs));
HttpResponse response = httpClient.execute(httpPost);
HttpEntity httpEntity = response.getEntity();
BufferedInputStream bis = new BufferedInputStream(httpEntity.getContent());
byte [] buffer;
while (0<bis.read(buffer=new byte[128])){
sb.append(new String(buffer,"utf-8"));
}
}catch (UnsupportedEncodingException e){//数据格式有误
e.printStackTrace();
}catch (IOException e){//请求出错
e.printStackTrace();
}finally {
httpPost.releaseConnection();
}
return sb.toString();
}
}
2.Oauth2Token类
package com.Ipwx;
/*
*登录配置
*/
public class Oauth2Token {
// 网页授权接口调用凭证
private String accessToken;
// 凭证有效时长
private int expiresIn;
// 用于刷新凭证
private String refreshToken;
// 用户标识
private String openId;
// 用户授权作用域
private String scope;
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public int getExpiresIn() {
return expiresIn;
}
public void setExpiresIn(int expiresIn) {
this.expiresIn = expiresIn;
}
public String getRefreshToken() {
return refreshToken;
}
public void setRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
}
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;
}
}
3.R 类
package com.Ipwx;
import java.util.HashMap;
import java.util.Map;
/**
* 返回数据
*
* @author xlf
* @email xlfbe696@gmail.com
* @date 2017年4月19日 上午11:58:56
*/
public class R extends HashMap<String, Object> {
private static final long serialVersionUID = 1L;
public static final String SUCCESS = "success";
public static final String EXCEPTION = "exception";
public static final Integer SUCCESSCODE = 0;
public static final Integer EXCEPTIONCODE = 500;
public R() {
put("errCode", 0);
put("msg", SUCCESS);
}
public R(int code, String msg){
put("errCode", code);
put("msg", msg);
}
public static R error() {
return error(500, "未知异常,请联系管理员");
}
public static R error(String msg) {
return error(500, msg);
}
public static R error(int code, String msg) {
R r = new R();
r.put("errCode", code);
r.put("msg", msg);
return r;
}
public static R ok(String msg) {
R r = new R();
r.put("msg", msg);
return r;
}
public static R ok(Map<String, Object> map) {
R r = new R();
r.putAll(map);
return r;
}
public static R ok() {
return new R();
}
public R put(String key, Object value) {
super.put(key, value);
return this;
}
}
4. SNSUserInfo 类
package com.Ipwx;
import java.util.List;
/**
* 类名: SNSUserInfo
* 描述: 通过网页授权获取的用户信息
*/
public class SNSUserInfo {
// 用户标识
private String openId;
// 用户昵称
private String nickname;
// 性别(1是男性,2是女性,0是未知)
private int sex;
// 国家
private String country;
// 省份
private String province;
// 城市
private String city;
// 用户头像链接
private String headImgUrl;
// 用户特权信息
private List<String> privilegeList;
private String unionid;
public String getUnionid() {
return unionid;
}
public void setUnionid(String unionid) {
this.unionid = 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 int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
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 getHeadImgUrl() {
return headImgUrl;
}
public void setHeadImgUrl(String headImgUrl) {
this.headImgUrl = headImgUrl;
}
public List<String> getPrivilegeList() {
return privilegeList;
}
public void setPrivilegeList(List<String> privilegeList) {
this.privilegeList = privilegeList;
}
}
5. WxController 方法
package com.Ipwx;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Formatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.manage.buser.pojo.Buser;
import com.manage.buser.service.IBuserService;
import com.util.Time;
import org.apache.http.client.utils.URLEncodedUtils;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.util.IOUtils;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
@RestController
@RequestMapping("/wx")
@ResponseBody
public class WxController {
@Resource
IBuserService buserService;
private static Logger log = LoggerFactory.getLogger(WxController.class);
/**
* 向指定URL发送GET方法的请求
*
// * @param url
// * 发送请求的URL
// * @param param
* 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
* @return URL 所代表远程资源的响应结果
*
* 用户同意授权,获取code
*/
@RequestMapping("/authorize")
@ResponseBody
// @IgnoreToken
public static R authorize() {
String appid = "";
//String uri ="wftest.zzff.net/wx/weixinLogin";
//微信登录回调的主要方法地址
String uri = urlEncodeUTF8("");
String result = "";
BufferedReader in = null;
try {
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";
URL realUrl = new URL(urlNameString);
// 打开和URL之间的连接
URLConnection connection = realUrl.openConnection();
// 设置通用的请求属性
connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 建立实际的连接
connection.connect();
// 获取所有响应头字段
Map<String, List<String>> map = connection.getHeaderFields();
// 遍历所有的响应头字段
for (String key : map.keySet()) {
System.out.println(key + "--->" + map.get(key));
}
// 定义 BufferedReader输入流来读取URL的响应
in = new BufferedReader(new InputStreamReader(
connection.getInputStream()));
String line =null;
while ((line = in.readLine()) != null) {
result += line;
}
/* com.alibaba.fastjson.JSONObject jsonObj= FastJSONUtils.getJSONObject(result);
String access_token = jsonObj.getString("access_token");
long expires_in = Long.valueOf(jsonObj.getString("expires_in"));
*/
} catch (Exception e) {
System.out.println("发送GET请求出现异常!" + e);
e.printStackTrace();
}
// 使用finally块来关闭输入流
finally {
try {
if (in != null) {
in.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
return R.ok(result);
}
@RequestMapping("/weixinLogin")
@ResponseBody
// @IgnoreToken
// @IgnoreSign
public ModelAndView weixinLogin(HttpServletRequest request,String state, HttpServletResponse response, HttpSession session) throws Exception {
// 用户同意授权后,能获取到code
Map<String, String[]> params = request.getParameterMap();//针对get获取get参数
String[] codes = params.get("code");//拿到code的值
String code = codes[0];//code
// String[] states = params.get("state");
// String state = states[0];//state
System.out.println("****************code:"+code);
// 用户同意授权
if (!"authdeny".equals(code)) {
// 获取网页授权access_token
//参数按需求更改(第一个参数为appid,第二个为appsecret)
Oauth2Token oauth2Token = getOauth2AccessToken("", code);
System.out.println("***********************************oauth2Token信息:"+oauth2Token.toString());
// 网页授权接口访问凭证
String accessToken = oauth2Token.getAccessToken();
// 用户标识
String openId = oauth2Token.getOpenId();
// 获取用户信息
SNSUserInfo snsUserInfo = getSNSUserInfo(accessToken, openId);
System.out.println("***********************************用户信息unionId:"+snsUserInfo.getUnionid()+"***:"+snsUserInfo.getNickname());
System.out.println(state);
// 设置要传递的参数
//具体业务start
Buser buser1 = new Buser();
buser1.setBuser1(snsUserInfo.getUnionid());
List<Buser> search = buserService.search(buser1);
if (search.size()>0){
session.setAttribute("buserLogin", search.get(0));
Buser buser = search.get(0);
buser.setBuserNickname(snsUserInfo.getNickname());
buser.setBuserImage(snsUserInfo.getHeadImgUrl());
String province = snsUserInfo.getProvince();
String city = snsUserInfo.getCity();
String country = snsUserInfo.getCountry();
buser.setBuserAddress(country + province + city);
buserService.updateSelective(buser,session);
return new ModelAndView("forward:/"+state);
}else {
Buser buser = new Buser();
String province = snsUserInfo.getProvince();
String city = snsUserInfo.getCity();
String country = snsUserInfo.getCountry();
buser.setBuserNickname(snsUserInfo.getNickname());
buser.setBuser1(snsUserInfo.getUnionid());
buser.setBuserImage(snsUserInfo.getHeadImgUrl());
buser.setBuserSex(snsUserInfo.getSex());
buser.setBuserAddress(snsUserInfo.getCity());
buser.setBuser4(snsUserInfo.getOpenId());
buser.setBuserAddress(country + province + city);
buser.setBuserLogin(2);
buser.setBuserTime(Time.Nowtime());
//生成一个用户编号
buser.setBuserNumber(com.util.UUID.getOrderIdByUUId());
boolean insert = buserService.insert(buser);
if (insert){
session.setAttribute("buserLogin", buser);
ModelAndView modelAndView = new ModelAndView("/pages/registered/entrance");
modelAndView.addObject("info",state);
return modelAndView;
}
}
//具体业务end
}
ModelAndView modelAndView = new ModelAndView("/pages/registered/entrance");
modelAndView.addObject("info",state);
return modelAndView;
}
/**
* 获取网页授权凭证
*
* @param appId 公众账号的唯一标识
* @param appSecret 公众账号的密钥
* @param code
* @return WeixinAouth2Token
*/
public static Oauth2Token getOauth2AccessToken(String appId, String appSecret, String code) {
Oauth2Token wat = null;
// 拼接请求地址
String requestUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
requestUrl = requestUrl.replace("APPID", appId);
requestUrl = requestUrl.replace("SECRET", appSecret);
requestUrl = requestUrl.replace("CODE", code);
// 获取网页授权凭证
com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject(NetUtil.get(requestUrl));
if (null != jsonObject) {
try {
wat = new Oauth2Token();
wat.setAccessToken(jsonObject.getString("access_token"));
wat.setExpiresIn(jsonObject.getInteger("expires_in"));
wat.setRefreshToken(jsonObject.getString("refresh_token"));
wat.setOpenId(jsonObject.getString("openid"));
wat.setScope(jsonObject.getString("scope"));
} catch (Exception e) {
wat = null;
int errorCode = jsonObject.getInteger("errcode");
String errorMsg = jsonObject.getString("errmsg");
log.error("获取网页授权凭证失败 errcode:{} errmsg:{}", errorCode, errorMsg);
}
}
return wat;
}
/**
* 通过网页授权获取用户信息
*
* @param accessToken 网页授权接口调用凭证
* @param openId 用户标识
* @return SNSUserInfo
*/
public static SNSUserInfo getSNSUserInfo(String accessToken, String openId) {
SNSUserInfo snsUserInfo = null;
// 拼接请求地址
String requestUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID";
requestUrl = requestUrl.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openId);
// 通过网页授权获取用户信息
com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject(NetUtil.get(requestUrl));
if (null != jsonObject) {
try {
snsUserInfo = new SNSUserInfo();
// 用户的标识
snsUserInfo.setOpenId(jsonObject.getString("openid"));
// 昵称
snsUserInfo.setNickname(jsonObject.getString("nickname"));
// 性别(1是男性,2是女性,0是未知)
snsUserInfo.setSex(jsonObject.getInteger("sex"));
// 用户所在国家
snsUserInfo.setCountry(jsonObject.getString("country"));
// 用户所在省份
snsUserInfo.setProvince(jsonObject.getString("province"));
// 用户所在城市
snsUserInfo.setCity(jsonObject.getString("city"));
// 用户头像
snsUserInfo.setHeadImgUrl(jsonObject.getString("headimgurl"));
// 用户特权信息
List<String> list = JSON.parseArray(jsonObject.getString("privilege"),String.class);
snsUserInfo.setPrivilegeList(list);
//与开放平台共用的唯一标识,只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。
snsUserInfo.setUnionid(jsonObject.getString("unionid"));
} catch (Exception e) {
snsUserInfo = null;
int errorCode = jsonObject.getInteger("errcode");
String errorMsg = jsonObject.getString("errmsg");
log.error("获取用户信息失败 errcode:{} errmsg:{}", errorCode, errorMsg);
}
}
return snsUserInfo;
}
/**
* URL编码(utf-8)
*
* @param source
* @return
*/
public static String urlEncodeUTF8(String source) {
String result = source;
try {
result = java.net.URLEncoder.encode(source, "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return result;
}
private static String byteToHex(final byte[] hash) {
Formatter formatter = new Formatter();
for (byte b : hash)
{
formatter.format("%02x", b);
}
String result = formatter.toString();
formatter.close();
return result;
}
private static String create_nonce_str() {
return UUID.randomUUID().toString();
}
private static String create_timestamp() {
return Long.toString(System.currentTimeMillis() / 1000);
}
}
2.前台主要方法
1.请求登录
location.href="https://open.weixin.qq.com/connect/oauth2/authorize?appid=*******&redirect_uri=https://******/wx/weixinLogin&response_type=code&scope=snsapi_userinfo&state=""#wechat_redirect";
//appid 商户号id
//redirect_uri 请求回调地址(此案例的地址在主要类的WxController里面)
//scope 授权类型
//state 携带参数
3.更改说明
1.具体的代码更改在内面都有注释
2.要主要商户号是否有该域名的权限
3.回调地址根据自己的具体业务更改