Java微信公众平台开发_05_微信网页授权
GitHub源码:https://github.com/shirayner/weixin_gz
一、本节要点
1.网页授权回调域名
登录微信公众平台后台, 开发 - 接口权限 - 网页服务 - 网页帐号 - 网页授权获取用户基本信息 - 修改,
这里填写的是域名(是一个字符串),而不是URL
2. 获取code
获取code的流程
(1)创建一个跳转按钮,链接为:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxa0064ea657f80062&redirect_uri=http%3A%2F%2Frayner.nat300.top%2Fweixin_gz%2FIDAuthentication.jsp&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect
(2)在jsp页面 IDAuthentication.jsp 上接收code
//1.接收code和state
String code= request.getParameter("code");
String state=request.getParameter("state");
3.通过code换取网页授权access_token
//3.通过code换取网页授权access_token
private static final String GET_ACCESSTOKEN_BYCODE_URL="https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code"; /**
* @desc : 3.通过code换取网页授权access_token
*
* @param appId 第三方用户唯一凭证
* @param appSecret 第三方用户唯一凭证密钥,即appsecret
* @param Code code作为换取access_token的票据,每次用户授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。
*
* @return
* access_token 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
* expires_in access_token接口调用凭证超时时间,单位(秒)
* refresh_token 用户刷新access_token
* openid 用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID
* scope 用户授权的作用域,使用逗号(,)分隔
*
* @throws Exception String
*/
public static JSONObject getAccessTokenByCode(String appId,String appSecret,String code) throws Exception {
//1.获取请求url
String url=GET_ACCESSTOKEN_BYCODE_URL.replace("APPID", appId).replace("SECRET", appSecret).replace("CODE", code); //2.发起GET请求,获取返回结果
JSONObject jsonObject=HttpHelper.doGet(url);
logger.info("jsonObject:"+jsonObject.toJSONString()); //3.解析结果,获取accessToken
JSONObject returnJsonObject=null;
if (null != jsonObject) {
//4.错误消息处理
if (jsonObject.getInteger("errcode")!=null && 0 != jsonObject.getInteger("errcode")) {
int errCode = jsonObject.getInteger("errcode");
String errMsg = jsonObject.getString("errmsg");
throw new Exception("error code:"+errCode+", error message:"+errMsg);
//5.成功获取accessToken
}else {
returnJsonObject=jsonObject;
}
} return returnJsonObject;
}
4.通过网页授权access_token 拉取用户信息
//3. 拉取用户信息(需scope为 snsapi_userinfo)——网页授权时
private static final String GET_SNS_USERINFO_URL="https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN"; /**
* @desc :3. 拉取用户信息(需scope为 snsapi_userinfo)——网页授权时
*
* @param accessToken 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
* @param openId 用户的唯一标识
*
* @return
* openid 用户的唯一标识
* nickname 用户昵称
* sex 用户的性别,值为1时是男性,值为2时是女性,值为0时是未知
* province 用户个人资料填写的省份
* city 普通用户个人资料填写的城市
* country 国家,如中国为CN
* headimgurl 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。
* privilege 用户特权信息,json 数组,如微信沃卡用户为(chinaunicom)
* unionid 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。
*
* @throws Exception JSONObject
*/
public static JSONObject getSNSUserInfo(String accessToken,String openId ) throws Exception {
//1.获取请求url
String url=GET_SNS_USERINFO_URL.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openId); //2.发起GET请求,获取返回结果
JSONObject jsonObject=HttpHelper.doGet(url);
logger.info("jsonObject:"+jsonObject.toJSONString()); //3.解析结果,获取菜单数据
JSONObject returnJsonObject=null;
if (null != jsonObject) { //4.错误消息处理
if (jsonObject.getInteger("errcode")!=null && 0 != jsonObject.getInteger("errcode")) {
int errCode = jsonObject.getInteger("errcode");
String errMsg = jsonObject.getString("errmsg");
throw new Exception("error code:"+errCode+", error message:"+errMsg);
//5.成功获取菜单数据
} else {
returnJsonObject= jsonObject;
}
} return returnJsonObject; }
二、代码实现
1.Token工具类—AuthHelper
package com.ray.weixin.gz.util; import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Formatter;
import java.util.UUID; import javax.servlet.http.HttpServletRequest; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import com.alibaba.fastjson.JSONObject;
import com.ray.weixin.gz.config.Env;
import com.ray.weixin.gz.service.invoice.InvoiceService; /**
* 微信公众号 Token、配置工具类
* @desc : AccessToken、Jsticket 、Jsapi
*
* @author: shirayner
* @date : 2017年9月27日 下午5:00:25
*/
public class AuthHelper {
private static final Logger logger = LogManager.getLogger(AuthHelper.class); //1.获取access_token的接口地址,有效期为7200秒
private static final String GET_ACCESSTOKEN_URL="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
//2.获取getJsapiTicket的接口地址,有效期为7200秒
private static final String GET_JSAPITICKET_URL="https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi"; //3.通过code换取网页授权access_token
private static final String GET_ACCESSTOKEN_BYCODE_URL="https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code"; /**
* @desc :1.获取access_token
*
* @param appId 第三方用户唯一凭证
* @param appSecret 第三方用户唯一凭证密钥,即appsecret
*
* @return
* access_token 获取到的凭证
* expires_in 凭证有效时间,单位:秒
* @throws Exception String
*/
public static String getAccessToken(String appId,String appSecret) throws Exception {
//1.获取请求url
String url=GET_ACCESSTOKEN_URL.replace("APPID", appId).replace("APPSECRET", appSecret); //2.发起GET请求,获取返回结果
JSONObject jsonObject=HttpHelper.doGet(url);
logger.info("jsonObject:"+jsonObject.toJSONString()); //3.解析结果,获取accessToken
String accessToken="";
if (null != jsonObject) {
//4.错误消息处理
if (jsonObject.getInteger("errcode")!=null && 0 != jsonObject.getInteger("errcode")) {
int errCode = jsonObject.getInteger("errcode");
String errMsg = jsonObject.getString("errmsg");
throw new Exception("error code:"+errCode+", error message:"+errMsg);
//5.成功获取accessToken
}else {
accessToken=jsonObject.getString("access_token");
}
} return accessToken;
} /**
* @desc :2.获取JsapiTicket
*
* @param accessToken 有效凭证
* @return
* @throws Exception String
*/
public static String getJsapiTicket(String accessToken) throws Exception {
//1.获取请求url
String url=GET_JSAPITICKET_URL.replace("ACCESS_TOKEN", accessToken); //2.发起GET请求,获取返回结果
JSONObject jsonObject=HttpHelper.doGet(url);
logger.info("jsonObject:"+jsonObject.toJSONString()); //3.解析结果,获取accessToken
String jsapiTicket="";
if (null != jsonObject) {
//4.错误消息处理
if (jsonObject.getInteger("errcode")!=null && 0 != jsonObject.getInteger("errcode")) {
int errCode = jsonObject.getInteger("errcode");
String errMsg = jsonObject.getString("errmsg");
throw new Exception("error code:"+errCode+", error message:"+errMsg);
//5.成功获取jsapiTicket
}else {
jsapiTicket=jsonObject.getString("ticket");
}
} return jsapiTicket;
} /**
* @desc : 3.通过code换取网页授权access_token
*
* @param appId 第三方用户唯一凭证
* @param appSecret 第三方用户唯一凭证密钥,即appsecret
* @param Code code作为换取access_token的票据,每次用户授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。
*
* @return
* access_token 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
* expires_in access_token接口调用凭证超时时间,单位(秒)
* refresh_token 用户刷新access_token
* openid 用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID
* scope 用户授权的作用域,使用逗号(,)分隔
*
* @throws Exception String
*/
public static JSONObject getAccessTokenByCode(String appId,String appSecret,String code) throws Exception {
//1.获取请求url
String url=GET_ACCESSTOKEN_BYCODE_URL.replace("APPID", appId).replace("SECRET", appSecret).replace("CODE", code); //2.发起GET请求,获取返回结果
JSONObject jsonObject=HttpHelper.doGet(url);
logger.info("jsonObject:"+jsonObject.toJSONString()); //3.解析结果,获取accessToken
JSONObject returnJsonObject=null;
if (null != jsonObject) {
//4.错误消息处理
if (jsonObject.getInteger("errcode")!=null && 0 != jsonObject.getInteger("errcode")) {
int errCode = jsonObject.getInteger("errcode");
String errMsg = jsonObject.getString("errmsg");
throw new Exception("error code:"+errCode+", error message:"+errMsg);
//5.成功获取accessToken
}else {
returnJsonObject=jsonObject;
}
} return returnJsonObject;
} /**
* @desc :4.获取前端jsapi需要的配置参数
*
* @param request
* @return String
*/
public static String getJsapiConfig(HttpServletRequest request){ //1.准备好参与签名的字段
//1.1 url
/*
*以http://localhost/test.do?a=b&c=d为例
*request.getRequestURL的结果是http://localhost/test.do
*request.getQueryString的返回值是a=b&c=d
*/
String urlString = request.getRequestURL().toString();
String queryString = request.getQueryString();
String queryStringEncode = null;
String url;
if (queryString != null) {
queryStringEncode = URLDecoder.decode(queryString);
url = urlString + "?" + queryStringEncode;
} else {
url = urlString;
} //1.2 noncestr
String nonceStr=UUID.randomUUID().toString(); //随机数
//1.3 timestamp
long timeStamp = System.currentTimeMillis() / 1000; //时间戳参数 String signedUrl = url; String accessToken = null;
String ticket = null; String signature = null; //签名 try {
//1.4 jsapi_ticket
accessToken=getAccessToken(Env.APP_ID, Env.APP_SECRET);
ticket=getJsapiTicket(accessToken); //2.进行签名,获取signature
signature=getSign(ticket,nonceStr,timeStamp,signedUrl); } catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} logger.info("accessToken:"+accessToken);
logger.info("ticket:"+ticket);
logger.info("nonceStr:"+nonceStr);
logger.info("timeStamp:"+timeStamp);
logger.info("signedUrl:"+signedUrl);
logger.info("signature:"+signature);
logger.info("appId:"+Env.APP_ID); String configValue = "{signature:'" + signature + "',nonceStr:'" + nonceStr + "',timeStamp:'"
+ timeStamp + "',appId:'" + Env.APP_ID + "'}";
logger.info("configValue:"+configValue); return configValue;
} /**
* @desc : 4.1 生成签名的函数
*
* @param ticket jsticket
* @param nonceStr 随机串,自己定义
* @param timeStamp 生成签名用的时间戳
* @param url 需要进行免登鉴权的页面地址,也就是执行dd.config的页面地址
* @return
* @throws Exception String
*/ public static String getSign(String jsTicket, String nonceStr, Long timeStamp, String url) throws Exception {
String plainTex = "jsapi_ticket=" + jsTicket + "&noncestr=" + nonceStr + "×tamp=" + timeStamp + "&url=" + url;
System.out.println(plainTex);
try {
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(plainTex.getBytes("UTF-8"));
return byteToHex(crypt.digest());
} catch (NoSuchAlgorithmException e) {
throw new Exception(e.getMessage());
} catch (UnsupportedEncodingException e) {
throw new Exception(e.getMessage());
}
} /**
* @desc :4.2 将bytes类型的数据转化为16进制类型
*
* @param hash
* @return
* String
*/
private static String byteToHex(byte[] hash) {
Formatter formatter = new Formatter();
for (byte b : hash) {
formatter.format("%02x", new Object[] { Byte.valueOf(b) });
}
String result = formatter.toString();
formatter.close();
return result;
} /** 5.获取前端所需发票签名参数
*
* @desc :
*(1)将 api_ticket、appid、timestamp、nonceStr、cardType的value值进行字符串的字典序排序。
*(2)再将所有参数字符串拼接成一个字符串进行sha1加密,得到cardSign。
*
* @return String
* timestamp :卡券签名时间戳
nonceStr : 卡券签名随机串
signType : 签名方式,默认'SHA1'
cardSign : 卡券签名
*
*/
public static String getInvoiceConfig(){
//1.准备好签名参数
//1.1 api_ticket 授权页ticket
String apiTicket=null;
try {
String accessToken = AuthHelper.getAccessToken(Env.APP_ID, Env.APP_SECRET);
apiTicket=InvoiceService.getAuthPageTicket(accessToken);
} catch (Exception e) {
logger.info("获取授权页ticket失败");
e.printStackTrace();
} //1.2 appid
String appId=Env.APP_ID; //1.3 timestamp 时间戳
String timeStamp = System.currentTimeMillis() / 1000 +""; //1.4 nonceStr 随机数
String nonceStr=UUID.randomUUID().toString(); //1.5 cardType
String cardType="INVOICE"; //2.获取签名
String cardSign=null;
try { cardSign = AuthHelper.getCardSign(apiTicket, appId, timeStamp, nonceStr, cardType); } catch (Exception e) {
logger.info("获取发票签名失败");
e.printStackTrace();
} String signType="SHA1"; logger.info("apiTicket:"+apiTicket);
logger.info("appId:"+appId);
logger.info("timeStamp:"+timeStamp);
logger.info("nonceStr:"+nonceStr);
logger.info("cardType:"+cardType);
logger.info("cardSign:"+cardSign);
logger.info("signType:"+signType); //3.返回前端所需发票签名参数
JSONObject jsonObject=new JSONObject();
jsonObject.put("timestamp", timeStamp);
jsonObject.put("nonceStr",nonceStr );
jsonObject.put("signType",signType );
jsonObject.put("cardSign", cardSign); String configValue = jsonObject.toJSONString();
logger.info("configValue:"+configValue); return configValue;
} /**
* @desc :5.1获取发票签名
*
* @param apiTicket 授权页ticket,见InvoiceService
* @param appId
* @param timeStamp 时间戳
* @param nonceStr 随机串
* @param cardType 填入INVOICE
* @return
* @throws Exception
* String
*/
public static String getCardSign(String apiTicket, String appId, String timeStamp, String nonceStr,String cardType) throws Exception {
//1.将 api_ticket、appid、timestamp、nonceStr、cardType的value值进行字符串的字典序排序。
//注意:是value值值
String[] array = new String[] { apiTicket, appId, timeStamp, nonceStr,cardType};
StringBuffer sb = new StringBuffer();
// 字符串排序
Arrays.sort(array);
for (int i = 0; i < 5; i++) {
sb.append(array[i]);
}
String plainTex = sb.toString(); //String plainTex = apiTicket+appId+cardType+nonceStr+timeStamp; System.out.println("plainTex:"+plainTex);
try {
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(plainTex.getBytes("UTF-8"));
return byteToHex(crypt.digest());
} catch (NoSuchAlgorithmException e) {
throw new Exception(e.getMessage());
} catch (UnsupportedEncodingException e) {
throw new Exception(e.getMessage());
}
} public static String getSHA1(String apiTicket, String appId, String timeStamp, String nonceStr,String cardType) throws Exception{
System.out.println("getSHA1-----------");
try {
String[] array = new String[] { apiTicket, appId, timeStamp, nonceStr,cardType};
StringBuffer sb = new StringBuffer();
// 字符串排序
Arrays.sort(array);
for (int i = 0; i < 5; i++) {
sb.append(array[i]);
}
String str = sb.toString();
logger.info("str:"+str);
// SHA1签名生成
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(str.getBytes());
byte[] digest = md.digest(); StringBuffer hexstr = new StringBuffer();
String shaHex = "";
for (int i = 0; i < digest.length; i++) {
shaHex = Integer.toHexString(digest[i] & 0xFF);
if (shaHex.length() < 2) {
hexstr.append(0);
}
hexstr.append(shaHex);
}
return hexstr.toString();
} catch (Exception e) {
e.printStackTrace();
throw new Exception("获取发票签名失败");
}
} }
2.用户管理业务类—UserService
package com.ray.weixin.gz.service.user; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import com.alibaba.fastjson.JSONObject;
import com.ray.weixin.gz.util.HttpHelper; /**@desc : 用户管理
*
* @author: shirayner
* @date : 2017年10月31日 下午5:37:08
*/
public class UserService {
private static final Logger logger = LogManager.getLogger(UserService.class); //1. 获取用户基本信息(UnionID机制)
private static final String GET_USERINFO_URL="https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
//2.1 获取用户列表(从指定的next_openid的下一个开始获取)
private static final String LIST_USER_URL="https://api.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN&next_openid=NEXT_OPENID";
//2.2 获取所有用户列表
private static final String LIST_ALLUSER_URL="https://api.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN";
//3. 拉取用户信息(需scope为 snsapi_userinfo)——网页授权时
private static final String GET_SNS_USERINFO_URL="https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN"; /**
* @desc :1.获取用户基本信息(UnionID机制)
*
* @param accessToken 有效凭证
* @param openId 普通用户的标识,对当前公众号唯一
*
* @return 用户详细信息
* subscribe 用户是否订阅该公众号标识,值为0时,代表此用户没有关注该公众号,拉取不到其余信息。
* openid 用户的标识,对当前公众号唯一
* nickname 用户的昵称
* sex 用户的性别,值为1时是男性,值为2时是女性,值为0时是未知
* city 用户所在城市
* country 用户所在国家
* province 用户所在省份
* language 用户的语言,简体中文为zh_CN
* headimgurl 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),
* 用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。
* subscribe_time 用户关注时间,为时间戳。如果用户曾多次关注,则取最后关注时间
* unionid 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。
* remark 公众号运营者对粉丝的备注,公众号运营者可在微信公众平台用户管理界面对粉丝添加备注
* groupid 用户所在的分组ID(兼容旧的用户分组接口)
* tagid_list 用户被打上的标签ID列表
*
* @throws Exception JSONObject
*/
public static JSONObject getUserInfo(String accessToken,String openId ) throws Exception {
//1.获取请求url
String url=GET_USERINFO_URL.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openId); //2.发起GET请求,获取返回结果
JSONObject jsonObject=HttpHelper.doGet(url);
logger.info("jsonObject:"+jsonObject.toJSONString()); //3.解析结果,获取菜单数据
JSONObject returnJsonObject=null;
if (null != jsonObject) { //4.错误消息处理
if (jsonObject.getInteger("errcode")!=null && 0 != jsonObject.getInteger("errcode")) {
int errCode = jsonObject.getInteger("errcode");
String errMsg = jsonObject.getString("errmsg");
throw new Exception("error code:"+errCode+", error message:"+errMsg);
//5.成功获取菜单数据
} else {
returnJsonObject= jsonObject;
}
} return returnJsonObject;
} /** 2.1 获取用户列表(从指定的next_openid的下一个开始获取)
*
* @desc :一次拉取调用最多拉取10000个关注者的OpenID,可以通过多次拉取的方式来满足需求。
*
* @param accessToken 调用接口凭证
* @param nextOpenId 从指定的next_openid的下一个开始获取
*
* @return
* total 关注该公众账号的总用户数
* count 拉取的OPENID个数,最大值为10000
* data 列表数据,OPENID的列表
* next_openid 拉取列表的最后一个用户的OPENID
*
* @throws Exception JSONObject
*/
public static JSONObject listUser(String accessToken,String nextOpenId ) throws Exception {
//1.获取请求url
String url=LIST_USER_URL.replace("ACCESS_TOKEN", accessToken).replace("NEXT_OPENID", nextOpenId); //2.发起GET请求,获取返回结果
JSONObject jsonObject=HttpHelper.doGet(url);
logger.info("jsonObject:"+jsonObject.toJSONString()); //3.解析结果,获取菜单数据
JSONObject returnJsonObject=null;
if (null != jsonObject) { //4.错误消息处理
if (jsonObject.getInteger("errcode")!=null && 0 != jsonObject.getInteger("errcode")) {
int errCode = jsonObject.getInteger("errcode");
String errMsg = jsonObject.getString("errmsg");
throw new Exception("error code:"+errCode+", error message:"+errMsg);
//5.成功获取菜单数据
} else {
returnJsonObject= jsonObject;
}
} return returnJsonObject;
} /**2.2获取所有用户列表
*
* @desc :一次拉取调用最多拉取10000个关注者的OpenID,可以通过多次拉取的方式来满足需求。
*
* @param accessToken 调用接口凭证
*
* @return
* total 关注该公众账号的总用户数
* count 拉取的OPENID个数,最大值为10000
* data 列表数据,OPENID的列表
* next_openid 拉取列表的最后一个用户的OPENID
*
* @throws Exception JSONObject
*/
public static JSONObject listAllUser(String accessToken) throws Exception {
//1.获取请求url
String url=LIST_ALLUSER_URL.replace("ACCESS_TOKEN", accessToken); //2.发起GET请求,获取返回结果
JSONObject jsonObject=HttpHelper.doGet(url);
logger.info("jsonObject:"+jsonObject.toJSONString()); //3.解析结果,获取菜单数据
JSONObject returnJsonObject=null;
if (null != jsonObject) { //4.错误消息处理
if (jsonObject.getInteger("errcode")!=null && 0 != jsonObject.getInteger("errcode")) {
int errCode = jsonObject.getInteger("errcode");
String errMsg = jsonObject.getString("errmsg");
throw new Exception("error code:"+errCode+", error message:"+errMsg);
//5.成功获取菜单数据
} else {
returnJsonObject= jsonObject;
}
} return returnJsonObject;
} /**
* @desc :3. 拉取用户信息(需scope为 snsapi_userinfo)——网页授权时
*
* @param accessToken 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
* @param openId 用户的唯一标识
*
* @return
* openid 用户的唯一标识
* nickname 用户昵称
* sex 用户的性别,值为1时是男性,值为2时是女性,值为0时是未知
* province 用户个人资料填写的省份
* city 普通用户个人资料填写的城市
* country 国家,如中国为CN
* headimgurl 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。
* privilege 用户特权信息,json 数组,如微信沃卡用户为(chinaunicom)
* unionid 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。
*
* @throws Exception JSONObject
*/
public static JSONObject getSNSUserInfo(String accessToken,String openId ) throws Exception {
//1.获取请求url
String url=GET_SNS_USERINFO_URL.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openId); //2.发起GET请求,获取返回结果
JSONObject jsonObject=HttpHelper.doGet(url);
logger.info("jsonObject:"+jsonObject.toJSONString()); //3.解析结果,获取菜单数据
JSONObject returnJsonObject=null;
if (null != jsonObject) { //4.错误消息处理
if (jsonObject.getInteger("errcode")!=null && 0 != jsonObject.getInteger("errcode")) {
int errCode = jsonObject.getInteger("errcode");
String errMsg = jsonObject.getString("errmsg");
throw new Exception("error code:"+errCode+", error message:"+errMsg);
//5.成功获取菜单数据
} else {
returnJsonObject= jsonObject;
}
} return returnJsonObject; } }
3.IDAuthentication.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@page language="java" import="com.ray.weixin.gz.config.*"%>
<%@page language="java" import="com.alibaba.fastjson.JSONObject"%>
<%@page language="java" import="com.ray.weixin.gz.util.*"%>
<%@page language="java" import="com.ray.weixin.gz.service.user.*"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>身份认证</title>
<script src="js/jquery-3.2.1.min.js"></script>
<script type="text/javascript"
src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script> </head>
<body> <%
//1.接收code和state
String code= request.getParameter("code");
String state=request.getParameter("state"); //2.获取网页授权时的accessToken 以及 openId
JSONObject jsonObject = AuthHelper.getAccessTokenByCode(Env.APP_ID,Env.APP_SECRET, code);
String accessToken=jsonObject.getString("access_token");
String openId=jsonObject.getString("openid"); //3.拉取用户信息
JSONObject userInfoJsonObject =UserService.getSNSUserInfo(accessToken, openId); %> hello,这里是第三方应用 code=<%= code%> <br>
state=<%= state%> <br>
nickname=<%= userInfoJsonObject.getString("nickname") %> <br><br>
sex=<%= userInfoJsonObject.getString("sex") %> <br><br>
headimgurl=<%= userInfoJsonObject.getString("headimgurl") %> <br><br> </body>
</html>
Java微信公众平台开发_05_微信网页授权的更多相关文章
- 微信公众平台开发-OAuth2.0网页授权(含源码)
微信公众平台开发-OAuth2.0网页授权接口.网页授权接口详解(含源码)作者: 孟祥磊-<微信公众平台开发实例教程> 在微信开发的高级应用中,几乎都会使用到该接口,因为通过该接口,可以获 ...
- 黄聪:微信公众平台开发OAuth2.0网页授权(转)
微信公众平台开发 OAuth2.0网页授权认证 网页授权获取用户基本信息 作者:方倍工作室 微信公众平台最近新推出微信认证,认证后可以获得高级接口权限,其中一个是OAuth2.0网页授权,很多朋友在使 ...
- 微信公众平台开发 OAuth2.0网页授权认证
一.什么是OAuth2.0 官方网站:http://oauth.NET/ http://oauth.Net/2/ 权威定义:OAuth is An open protocol to allow s ...
- php 微信公众平台开发之微信群发信息
这篇文章主要为大家详细介绍了php微信公众平台开发之微信群发信息,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 1.目的 完成在微信公众号中群发消息.这里只是完成简单的文字发送.也可以发送语音图片 ...
- Java微信公众平台开发(十)--微信用户信息的获取
前面的文章有讲到微信的一系列开发文章,包括token获取.菜单创建等,在这一篇将讲述在微信公众平台开发中如何获取微信用户的信息,在上一篇我们有说道微信用户和微信公众账号之间的联系可以通过Openid关 ...
- 微信公众平台开发(110) 微信连Wi-Fi
关键字:微信公众平台 微信连Wi-Fi 微信 WiFi 硬件鉴权作者:方倍工作室 原文:http://www.cnblogs.com/txw1958/p/weixin-wifi.html 微信连Wi- ...
- Java微信公众平台开发(十三)--微信JSSDK中Config配置
转自:http://www.cuiyongzhi.com/post/57.html 前端开发工程师和关注前端开发的开发者们在2015年中肯定被腾讯的JSSDk引爆过,搞APP的.搞前端的甚至是是搞后端 ...
- Java微信公众平台开发(十)--微信自定义菜单的创建实现
转自:http://www.cuiyongzhi.com/post/48.html 自定义菜单这个功能在我们普通的编辑模式下是可以直接在后台编辑的,但是一旦我们进入开发模式之后我们的自定义菜单就需要自 ...
- Java微信公众平台开发(十一)--微信JSSDK中Config配置
JSSDK曾经引爆前端以及后端的工程师,其魔性的力量毋庸置疑,在我们的技术眼里它的实现原理和根本是不能够被改变的,这篇文章就不对其js的实现做任何评价和解说了(因为我也不是很懂,哈哈),这里要说的是它 ...
随机推荐
- servlet实现文件下载所需步骤及说明
servlet实现文件下载所需步骤及说明 CreateTime--2017年9月1日15:46:22 Author:Marydon 参考链接:http://blog.sina.com.cn/s/b ...
- matlab-2
function varargout = gmm(X, K_or_centroids) % ====================================================== ...
- CSS3 background属性
background: #00FF00 url(bgimage.gif) no-repeat fixed top; background 简写属性在一个声明中设置所有的背景属性. 可以设置如下属性: ...
- Cocos2d-x 更改文字换行风格 ( cocos2dx change line )
Cocos2dx change line 在 cocos2dx change line 的实现中,我们能够简单的使用 dimensions属性控制换行.使用它仅仅需将相应的參数值传入构造函数,或者调用 ...
- UML类图简明教程
作者:郭孝星 微博:郭孝星的新浪微博 邮箱:allenwells@163.com 博客:http://blog.csdn.net/allenwells Github:https://github.co ...
- jQuery源代码 框架分析
每个框架都有一个核心.全部的结构都是基于这个核心之上,结构建立好了之后,剩下的就是功能的堆砌. jQuery的核心就是从HTML文档中匹配元素并对其操作. 就跟一座大楼一样.让我们一步一步了解这座大厦 ...
- Python操作Execl 实现自动化填表
任务简述: 表1是一个简单的数据表,共有110行,25列.第1行是表头,例如“负责人”.“事项”.“期限”等. 第2行——第110行是对应的数据,如“张三”.“搬砖头”.“3天”. 想要做的表(表2) ...
- apt-mirror 校验错误文件处理
apt-mirror是一个用来将Debian或Ubuntu的软件源镜像到本地的工具,这个工具工作得非常好,不过有的时候由于网络问题,会有一些文件的校验是失败的,但apt-mirror并不能发现,等到最 ...
- Struts2实现input数据回显
/** 修改页面 */ public String editUI() { //准备回显得数据 Role role = roleService.getById(id); ...
- 【翻译自mos文章】关于分区索引:Global, Local, Prefixed and Non-Prefixed
来源于: Partitioned Indexes: Global, Local, Prefixed and Non-Prefixed (文档 ID 69374.1) APPLIES TO: Oracl ...