微信获取用户信息和微信分享相似,也分为app端获取用户信息和分享页面获取用户信息.
app端获取用户信息,较为简单固定,不管是用Hbuilder还是原生开始,或者只是原生打壳开发,都是集成了微信sdk.直接调用接口,并对返回数据进行解析即可.
主要是第三方分享页面中获取用户信息.
现在有这么一个需求,用户通过点击分享链接进入到分享页面之后,要求实现自动点赞功能.这就需要获取到当前用户的个人信息.
需要准备的原材料:
1.有独立域名的服务器,获取用户信息时,微信服务器会发起回调,将结果返回到业务服务器接口.
2.申请服务号,并进行认证,认证费用暂时为300/年.
3.根据微信机制,用户在app端有一个独立的openid,在服务号端也有一个独立的openid,两个openid是不相同的,这就造成了app端和在分享页面通过服务号获取到的用户信息不能同步.而业务又限制了两个信息必须同步,所以需要在腾讯开放平台上绑定服务号,用来获取unionid,这样才能在微信中打通app端和服务号端的用户信息.
完成之后,按照步骤进行.
1.前端页面,因为获取微信用户信息,就需要微信回调,如果直接在业务页面进行微信信息的获取和回调,页面会明显看到加载出来之后,又重新加载了一遍,体验不好,所以在业务页面之前重新建立一个页面,主要是微信信息获取的逻辑实现和跳转,html尽量保持简单.回调也回调该页面,拿到用户信息之后,再跳转到业务页面,这样,即使在该页面有两次载入,也只是上边进度条有从头载入两次,页面内容不会有明显变化(该页面本身也就故意设置的没什么内容)
var appid ='公众号appid';
var redirect_uri='';//微信回调地址,需要对地址就行转码
window.οnlοad=function(){
var ua = window.navigator.userAgent.toLowerCase();
if(ua.match(/MicroMessenger/i) == 'micromessenger'){
wechatBrowserRoad();
}else{
otherOrdinaryBrowser();// 避免用户分享到微博之类不是微信浏览器的环境,不能正常打开
}
}
function otherOrdinaryBrowser(){// 非微信浏览器
window.location.href='';// 直接跳转
}
function wechatBrowserRoad(){// 如果是微信浏览器,则走该条逻辑
var groupId = '';
// var paratype="groupval";
var paratype = '';
paratype = getQueryString("paratype");
var code = getQueryString("code");
if(isNotNull(code)){// code 不为空,为从微信服务器跳回的链接,直接根据传过去的参数获取groupid-paratype
var useStateChuanPara=getQueryString('state');// 额外需要传递的参数,传递到微信服务器之后,再从微信服务器返回
queryUserinfoWithCode();
}else{ // code 为空,则为从分享链接过来
groupId = getQueryString("groupId");// 接收从分享链接跳转传递过来的参数
paratype = getQueryString("paratype");// 接收从分享链接跳转传递过来的参数
var useStateChuanPara=groupId+'-'+paratype ;
// 首先根据返回的code使用snsapi_base获取到用户openid之后,去数据库获取用户的信息
// 如果用户信息存在,则直接返回,如果用户信息不存在,则使用 snsapi_userinfo的方式重新获取用户信息
var scopetype ="snsapi_base";
jQuery('#groupId').val(groupId);
jQuery('#paratype').val(paratype);
window.location.href="https://open.weixin.qq.com/connect/oauth2/authorize?appid="+appid+"&redirect_uri="+redirect_uri+"&response_type=code&scope="+scopetype+"&state="+useStateChuanPara+"#wechat_redirect";
}
}
//获取url参数
function getQueryString(name){
var reg = new RegExp("(^|&)"+ name +"=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
if(r!=null)return unescape(r[2]); return null;
}
function queryUserinfoWithCode(){
var _code = jQuery('#code').val();
var groupId = jQuery('#groupId').val();
var paratype = jQuery('#paratype').val();
var code_url = '';
jQuery.ajax({
url: code_url,
type: 'POST',
data : {'wechatcode':_code},
dataType: 'json',
asyn:true,
success:function(_json){
if(_json.status=="snsapi_baseusernull"){// 根据用户 snsapi_base方式获取信息,信息不存在
var scopetype ="snsapi_userinfo";
var useStateChuanPara=groupId+'-'+paratype ;
window.location.href="https://open.weixin.qq.com/connect/oauth2/authorize?appid="+appid+"&redirect_uri="+redirect_uri+"&response_type=code&scope="+scopetype+"&state="+useStateChuanPara+"#wechat_redirect";
}else if(_json.status=="newcreateaccount"){// 如果用户信息在服务器不存在,则需要创建,
if(_json.data != null && _json.data != ''){
window.location.href='';
}
}else if(_json.status=="openidalreadyexists"){// 已经存在,则直接返回
window.location.href='';
}
}
});
}
服务器端逻辑:
ReturnDatas returnObject = ReturnDatas.getSuccessReturnDatas();
// 1.请求微信服务器获取code
String appid = "";// 测试appid
String secret = "";//测试
String METHOD = "POST";
String encode = "UTF-8";
String url = "";
String para = "";
String result = "";
String openid = "";
String access_token="";
String code = request.getParameter("wechatcode");
String scopetype = "";
String unionid="";
//1.根据code获取用户openid
url = "https://api.weixin.qq.com/sns/oauth2/access_token";
para = "appid="+appid+"&secret="+secret+"&code="+code+"&grant_type=authorization_code";
try {
result = HttpUtils.post(url, para, METHOD, encode);
} catch (Exception e) {
}
if(StringUtils.isNotBlank(result)){
HashMap<String, String> map_result = JsonUtils.readValue(result, HashMap.class);
openid = map_result.get("openid");
unionid = map_result.get("unionid");
scopetype = map_result.get("scope");
access_token = map_result.get("access_token");
System.out.println("第一步:openid:"+openid+";unionid:"+unionid);
if((StringUtils.isBlank(openid) || StringUtils.isBlank(unionid))&&(StringUtils.isNotBlank(scopetype) && "snsapi_userinfo".equalsIgnoreCase(scopetype))){
System.out.println("返回的openid 或者 unionid 为空");
returnObject.setMessage("返回的openid 或者 unionid 为空");
return returnObject ;
}
}
// 2. 首先根据返回的openid查询是否有绑定的用户,如果没有,则去微信服务器获取用户信息,创建新用户
SpMember queryGongzhongHaoMember = new SpMember();
if(StringUtils.isNotBlank(scopetype) && "snsapi_base".equalsIgnoreCase(scopetype)){
queryGongzhongHaoMember.setGongzhonghaoopenid(openid);
}else if(StringUtils.isNotBlank(scopetype) && "snsapi_userinfo".equalsIgnoreCase(scopetype)){
queryGongzhongHaoMember.setUnionid(unionid);
}
try {
queryGongzhongHaoMember=spMemberService.queryForObject(queryGongzhongHaoMember);
} catch (Exception e) {
}
if(queryGongzhongHaoMember != null &&
StringUtils.isBlank(queryGongzhongHaoMember.getGongzhonghaoopenid())){
queryGongzhongHaoMember.setGongzhonghaoopenid(openid);// 更新微信公众号id
try {
spMemberService.update(queryGongzhongHaoMember);
} catch (Exception e) {
}
}
if(queryGongzhongHaoMember != null ){
returnObject.setStatus("openidalreadyexists");
returnObject.setMessage("已创建用户,返回成功!");
returnObject.setData(queryGongzhongHaoMember);
return returnObject ;
}else if(queryGongzhongHaoMember == null && "snsapi_base".equalsIgnoreCase(scopetype)){
returnObject.setStatus("snsapi_baseusernull");
returnObject.setMessage("用户不存在");
returnObject.setData(null);
return returnObject ;
}
// 3.根据openid获取用户信息
url = "https://api.weixin.qq.com/sns/userinfo";
para = "access_token="+access_token+"&openid="+openid+"&lang=zh_CN";
try {
result = HttpUtils.post(url, para, METHOD, encode);
} catch (Exception e) {
}
HashMap<String, Object> user_info_map = null ;
if(StringUtils.isNotBlank(result)){
user_info_map = JsonUtils.readValue(result, HashMap.class);
}
String uploads = request.getSession().getServletContext().getRealPath("uploads");
if(user_info_map == null ){
returnObject.setData(null);
returnObject.setStatus(ReturnDatas.ERROR);
returnObject.setMessage("根据token返回的用户信息为空");
return returnObject ;
}
user_info_map.put("uploads", uploads);
// 4.根据微信返回的用户信息创建账号
SpMember createMember = null ;
try {
createMember = gefMemberRegisterService.createMemberinfoWithWechatUserinfo(user_info_map);
} catch (Exception e) {
returnObject.setData(null);
returnObject.setStatus(ReturnDatas.ERROR);
returnObject.setMessage("创建新用户信息失败");
return returnObject ;
}
returnObject.setData(createMember);
returnObject.setStatus("newcreateaccount");
return returnObject ;
为了避免前端每次都弹出用户授权页面,降低用户体验,在逻辑上,首先使用 snsapi_base(不会弹出用户授权页面) 方式去服务器获取用户信息,如果用户信息不存在再使用 snsapi_userinfo 方式去微信服务器获取用户信息,此时就一定会弹出用户授权页面.
以上.