1.最近在开发小程序的项目中,服务端需要配合前端获取当前用户与微信绑定的手机号;需要以下两步:
1.1根据前端所传的code通过服务端调微信接口获取openId,sessionkey;
1.2根据前端所传的encrypdata,ivdata,sessionKey服务端进行解密后得到手机号
2.登录根绝凭证appId和appSecret校验。通过 wx.login 接口获得临时登录凭证 code 后传到开发者服务器调用此接口完成登录流程,然后后端通过code值调用微信的API地址 获取openId和sessionkey信息 然后前端页面通过点击授权按钮触(encrypdata、ivdata,sessionKey)调用后端接口进行解密获取授权用户信息
3.开发流程如下 首先在配置文件里面配置appId和appSecret 如下图:
4.获取微信openId sessionKey工具类 代码如下:
package com.longjin.wechat.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
/**
* 请求微信小程序 api
*/
public class WeChatMiniClient {
/**
* 请求微信小程序api 获取 openId,session_key
*
* @param code wx.login返回 code值
* @param appId 小程序 appId
* @param appSecret 小程序 appSecret
* @return
*/
public static JSONObject feighMini(String code, String appId, String appSecret) {
//拼接url
StringBuilder url = new StringBuilder("https://api.weixin.qq.com/sns/jscode2session?");
url.append("appid=");//appId设置
url.append(appId);
url.append("&secret=");//secret设置
url.append(appSecret);
url.append("&js_code=");//code设置
url.append(code);
url.append("&grant_type=authorization_code"); //值固定
JSONObject jsonObject = new JSONObject();
try {
HttpClient client = HttpClientBuilder.create().build();//构建一个Client
HttpGet get = new HttpGet(url.toString()); //构建一个GET请求
HttpResponse response = client.execute(get);//提交GET请求
HttpEntity result = response.getEntity();//拿到返回的HttpResponse的"实体"
String content = EntityUtils.toString(result);
jsonObject = JSON.parseObject(content);
} catch (Exception e) {
e.printStackTrace();
}
return jsonObject;
}
}
5.调用工具类获取到sessionkey和openid放入redis中 等前端点用户授权之后和encrypdata、ivdata一起传过来,注意这里不要直接把sessionkey直接放到sessionkey放到接口中返到前端,sessionkey属于私密信息 我这里是保存到redis中 代码如下:
public Map<String, Object> loginAuto(String code) throws Exception {
Map<String, Object> map = new HashMap<>();
//请求小程序api
JSONObject jsonObject = WeChatMiniClient.feighMini(code, caseAppId, caseAppSecret);
Map<String, Object> tempMap = AllJsonUtils.convertJson2Object(jsonObject, Map.class);
//包含错误码
if (tempMap.containsKey("errcode")) {
String errCode = tempMap.get("errcode").toString();
//错误 非法请求
//系统返回msg,携带英文
String sysMsg = tempMap.get("errmsg").toString();
map.put("errorCode", errCode);
map.put("errorMsg", MiniConstants.getMsg(errCode, sysMsg));
} else if (tempMap.containsKey("session_key")) {
//获取用户唯一标识
String openId = tempMap.get("openid").toString();
map.put("openId",openId);
//将openId与sessionKey关联 放入缓存中
redisUtil.setex(openId, tempMap.get("session_key").toString(), Contents.appRedisLoginTimeOut, Contents.userIndexdb);
}
return map;
}
6.点击授权获取手机号码 代码如下:
/**
* <desc>
* 解密与微信绑定的手机号
* </desc>
*
* @param encrypdata 微信参数
* @param ivdata 微信参数
* @param sessionKey 会话密钥
* @return
* @createDate 2018/11/24
*/
@RequestMapping(path = "/getPhoneNum",method = RequestMethod.POST)
@ResponseBody
public MessageVO getPhoneNum(String encrypdata,String ivdata,String sessionKey){
try {
if(StringUtils.isEmpty(encrypdata) || StringUtils.isEmpty(ivdata) || StringUtils.isEmpty(sessionKey)){
return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
}
byte[] encrypData = Base64.decode(encrypdata);
byte[] ivData = Base64.decode(ivdata);
byte[] sessionKeyByte = Base64.decode(sessionKey);
AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivData);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec keySpec = new SecretKeySpec(sessionKeyByte, "AES");
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
//解析解密后的字符串
String phoneNum = new String(cipher.doFinal(encrypData),"UTF-8"); JSONObject jsonObjects = JSONObject.parseObject(json);
String phoneNumber = jsonObjects.getString("phoneNumber");//用户手机号
return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(),phoneNum);
}catch (Exception e){
throw new DataAccessException("【小程序_注册登录版块】解密与微信绑定的手机号失败",e);
}
}
7.以上就是获取授权之后的用户手机号码 令附上项目中实际应用 代码如下:
@Override
public ResultsCode saveUserInfo(GlobalUser globalUser){
try {
String sessionKey = "";
sessionKey = redisUtil.get(globalUser.getOpenId(), Contents.userIndexdb);
//sessionKey查询不到查数据库
if(StringUtils.isBlank(sessionKey)){
VipThirdAccountUser vipThirdAccountUser = vipThirdAccountUserDao.findByAccountId(globalUser.getOpenId());
sessionKey = vipThirdAccountUser.getAccountKey();
}
byte[] encrypData = com.sun.org.apache.xerces.internal.impl.dv.util.Base64.decode(globalUser.getEncryptedData());
byte[] ivData = com.sun.org.apache.xerces.internal.impl.dv.util.Base64.decode(globalUser.getIv());
byte[] sessionKeyByte = Base64.decode(sessionKey);
AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivData);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec keySpec = new SecretKeySpec(sessionKeyByte, "AES");
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
//解析解密后的字符串
String json = new String(cipher.doFinal(encrypData),"UTF-8");
JSONObject jsonObjects = JSONObject.parseObject(json);
String phoneNumber = jsonObjects.getString("phoneNumber");
//通过openId查询
VipThirdAccountUser vipThirdAccountUser = vipThirdAccountUserDao.findByAccountId(globalUser.getOpenId());
Map<String,Object> map = new HashMap<>();
//没有对应数据 加入用户数据
if (null == vipThirdAccountUser) {//新用户
globalUser.setAccountId(globalUser.getOpenId());
globalUser.setPhone(phoneNumber);
globalUser.setAccountKey(sessionKey);
addUserInfo(globalUser);
} else {//老用户
String username = vipThirdAccountUser.getUsername();
GlobalUser byUserName = globalUserDao.findByUserName(username);
if (null != byUserName) {
doCommon(map, byUserName, globalUser.getOpenId());
return ResultsCode.success(map);
}
}
}catch (Exception e){
return ResultsCode.Fail();
}
return ResultsCode.success();
}
/**
* 设置公共部分
*/
public void doCommon(Map<String, Object> map, GlobalUser globalUser, String openId) {
//判断是否存在对应key
boolean loginExist = redisUtil.exists(SysStringUtils.md5(globalUser.getUsername() + "mini"), Contents.userIndexdb);
if (loginExist) {
String oldToken = redisUtil.get(SysStringUtils.md5(globalUser.getUsername() + "mini"), Contents.userIndexdb);
redisUtil.del(Contents.userIndexdb, oldToken);
}
GlobalUserExt globalUserExt = globalUserExtDao.findByUserId(globalUser.getUserId().toString());
globalUser.setNickname(globalUserExt.getNickname());
globalUser.setImagePath(globalUserExt.getImagePath());
globalUser.setWeixinId(globalUserExt.getWeixinId());
map.put("globalUser", globalUser);
String token = TokenUtils.getToken(globalUser.getUserId().toString(), globalUser.getUsername(), SysStringUtils.md5(globalUser.getUsername() + "caseMini"), globalUser.getUserId().toString());
map.put("token", token);
map.put("openId", openId);
//将生成的token存入Redis中
redisUtil.setex(token, token, Contents.appRedisLoginTimeOut, Contents.userIndexdb);
redisUtil.setex(SysStringUtils.md5(globalUser.getUsername() + "mini"), token, Contents.appRedisLoginTimeOut, Contents.userIndexdb);
AdminRole role = new AdminRole();
role.setUserId(globalUser.getUserId());
List<AdminRole> roleList = roleManageService.getRoleList(role);
map.put("roleList", roleList);
//获取角色全部菜单资源列表
List<AdminMenu> adminMenuList = new ArrayList<>();
if (null != roleList && roleList.size() != 0) {
for (AdminRole r : roleList) {
List<AdminMenu> roleMenuList = roleManageService.getRoleMenuList(r.getRoleId());
adminMenuList.addAll(roleMenuList);
}
}
map.put("adminMenuList",adminMenuList);
String uid = globalUser.getUserId().toString();
new Thread() {
@Override
public void run() {
if (StringUtils.isNotBlank(uid)) {
globalUserDao.updateStatus(uid);
}
}
}.start();
}
/**
* 添加用户信息
*
* @param globalUser
*/
public void addUserInfo(GlobalUser globalUser){
//用户统一信息添加
String userId = StringStrUtils.getUUID();
globalUser.setSource(NumberEnum.FIRST.code());
globalUser.setMobile(globalUser.getPhone());
globalUser.setUsername(globalUser.getPhone());
globalUser.setCreateType(NumberEnum.SECOND.code());
globalUser.setUserId(userId);
globalUserDao.save(globalUser);
//会员用户添加
VipMemberUser vipMemberUser = new VipMemberUser();
vipMemberUser.setUserId(userId);
Integer memberId = vipMemberUserDao.save(vipMemberUser);
//三方授权登录添加
VipThirdAccountUser vipThirdAccountUser = new VipThirdAccountUser();
vipThirdAccountUser.setMemberId(memberId);
vipThirdAccountUser.setSource(globalUser.getThirdAccountSource());
vipThirdAccountUser.setAccountId(globalUser.getAccountId());
vipThirdAccountUser.setAccountKey(globalUser.getAccountKey());
vipThirdAccountUser.setUserId(userId);
vipThirdAccountUser.setUsername(globalUser.getPhone());
vipThirdAccountUserDao.save(vipThirdAccountUser);
AdminRole role = new AdminRole();
role.setAppId("PA-PLATFORM-XH");
role.setRoletypeId("R32");
role.setName("市民");
role.setCode("CITIZEN");
role.setPriority(NumberEnum.FIVE.code());
role.setIsRegular(NumberEnum.FIRST.code());
role.setIsSuper(NumberEnum.ZERO.code());
role.setIsPublic(NumberEnum.ZERO.code());
role.setStatus(NumberEnum.FIRST.code());
role.setDescription("市民");
role.setUserId(userId);
Integer roleId = roleManageService.add(role);
//会员用户组
SasMemberGroup sasMemberGroup = new SasMemberGroup();
sasMemberGroup.setRoleId(roleId);
sasMemberGroup.setName("市民");
sasMemberGroup.setCode("CITIZEN");
sasMemberGroup.setIsCommonGroup(NumberEnum.FIRST.code());
sasMemberGroup.setIsLeaderGroup(NumberEnum.ZERO.code());
sasMemberGroup.setIsGridGroup(NumberEnum.ZERO.code());
sasMemberGroup.setIsPartyGroup(NumberEnum.ZERO.code());
sasMemberGroup.setIsWorkGroup(NumberEnum.ZERO.code());
sasMemberGroup.setIsVillageGroup(NumberEnum.ZERO.code());
sasMemberGroup.setIsDisabled(NumberEnum.ZERO.code());
sasMemberGroup.setPriority(NumberEnum.FIRST.code());
sasMemberGroup.setDescription("市民");
Integer groupId = sasMemberGroupDao.add(sasMemberGroup);
//添加用户组关联
SasMemberGroupUser sasMemberGroupUser = new SasMemberGroupUser();
sasMemberGroupUser.setGroupId(groupId);
sasMemberGroupUser.setMemberId(memberId);
sasMemberGroupUserDao.add(sasMemberGroupUser);
//添加用户基本信息
GlobalUserExt globalUserExt = new GlobalUserExt();
globalUserExt.setUserId(userId);
globalUserExt.setNickname(globalUser.getNickname());
globalUserExt.setWeixinId(globalUser.getWeixinId());
globalUserExt.setImagePath(globalUser.getImagePath());
globalUserExtDao.save(globalUserExt);
}