一、登录流程
1.前端先通过wx.login获取用户登录临时凭证和getPhoneNumber接口获取手机号凭证,然后传给后端。
2.后端通过用户登录凭证调用微信接口可以得到openid,通过手机号凭证调取微信接口可以得到手机号。
3.然后通过openid查询数据库有没有,如果没有的话就新增,如果有的话就更新用户信息(如手机号、修改时间)。
4.生成令牌和昵称并响应给后端。
二、登录后端难点详解:得到手机号+openid
1.要想获取手机号 就要得到必须得请求参数access_token和手机号凭证Code 。
(1)得到access_token:通过GET请求https://api.weixin.qq.com/cgi-bin/token响应获取。

(2)手机号凭证Code: 通过前端的bindgetphonenumber方法获取然后传入后端的
2.得到获取手机号:通过POST 请求 https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=xxx 获取。

3.获取openid :通过GET请求https://api.weixin.qq.com/sns/jscode2session获取。

三、主要核心代码如下:
packagecom.zzyl.service.impl;importcn.hutool.http.*;importcn.hutool.json.JSONObject;importcn.hutool.json.JSONUtil;importcom.zzyl.dto.MemberDto;importcom.zzyl.entity.Member;importcom.zzyl.enums.BasicEnum;importcom.zzyl.exception.BaseException;importcom.zzyl.mapper.MemberMapper;importcom.zzyl.service.MemberService;importcom.zzyl.utils.JwtUtil;importcom.zzyl.utils.StringUtils;importcom.zzyl.vo.LoginVo;importlombok.extern.slf4j.Slf4j;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.stereotype.Service;importjava.util.HashMap;importjava.util.Map;@Slf4j@ServicepublicclassMemberServiceImplimplementsMemberService{@AutowiredprivateMemberMapper memberMapper;@Value("${wx.appid}")privateString appid;@Value("${wx.secret}")privateString secret;privatestaticfinalStringBASE_URL="https://api.weixin.qq.com";@OverridepublicLoginVologin(MemberDto dto){// 1.获取oppenidString openId =getOpenid(dto.getCode());// 2.获取手机号凭证String accessToken =getAccessToken();// 3.获取手机号String phone =getPhone(dto.getPhoneCode(), accessToken);// 4.根据openid查询数据库 如果有的话就修改手机号, 没有就新增Member member =null;try{
member = memberMapper.selectByOpenId(openId);}catch(Exception e){thrownewRuntimeException(e);}if(StringUtils.isNull(member)){String name ="微信用户"+ phone.substring(7);// builder是简化对象的构建过程,可以理解为多参构造器
member =Member.builder().openId(openId).phone(phone).name(name).build();
memberMapper.insert(member);}else{
member.setPhone(phone);
memberMapper.update(member);}// 5.登录成功设置令牌LoginVo loginVo =newLoginVo();Map<String,Object> clams =newHashMap<>();try{
clams.put("id", member.getId());
clams.put("name", member.getName());String token =JwtUtil.createJWT(secret,24, clams);
loginVo.setToken(token);}catch(Exception e){thrownewBaseException(BasicEnum.SYSYTEM_FAIL);}
loginVo.setNickName(member.getName());return loginVo;}/**
* 获取手机号令牌token
* @return
*/privateStringgetAccessToken(){String url ="/cgi-bin/token";Map<String,Object> params =newHashMap<>();
params.put("grant_type","client_credential");
params.put("appid", appid);
params.put("secret", secret);String token =null;try{String resStr =HttpUtil.get(BASE_URL+ url, params);
token =(String)JSONUtil.parseObj(resStr).get("access_token");}catch(Exception e){thrownewBaseException(BasicEnum.GET_TOKEN_ERROR);}return token;}/**
* 获取手机号
* @param phoneCode 手机号获取凭证(前端登录传入的)
* @param accessToken 手机号接口调用凭证
* @return
*/privateStringgetPhone(String phoneCode,String accessToken){String url ="/wxa/business/getuserphonenumber";Map<String,Object> bodys =newHashMap<>();
bodys.put("code", phoneCode);String phone =null;try{HttpRequest request =HttpUtil.createRequest(Method.POST,BASE_URL+ url+"?access_token="+accessToken);
request.body(JSONUtil.toJsonStr(bodys));HttpResponse response = request.execute();String resStr =response.body();Object phoneInfo =JSONUtil.parseObj(resStr).get("phone_info");
phone =JSONUtil.parseObj(phoneInfo).getStr("phoneNumber");return phone;}catch(Exception e){thrownewBaseException(BasicEnum.GET_PHONE_ERROR);}}/**
* 根据code获取用户在小程序的唯一标识
*
* @param code
* @return
*/privateStringgetOpenid(String code){String url ="/sns/jscode2session";Map<String,Object> params =newHashMap<>();
params.put("appid", appid);
params.put("secret", secret);
params.put("js_code", code);
params.put("grant_type","authorization_code");JSONObject resObj =null;Object errcode =null;try{HttpRequest request =HttpUtil.createRequest(Method.POST,BASE_URL+ url).form(params);HttpResponse response = request.execute();
resObj =JSONUtil.parseObj(response.body());
errcode = resObj.get("errcode");}catch(HttpException e){thrownewBaseException(BasicEnum.SYSYTEM_FAIL);}
log.info("resObj: {}", resObj);if(errcode !=null){thrownewBaseException(BasicEnum.GET_OPENID_ERROR);}return(String) resObj.get("openid");}}
相关链接:微信小程序实现手机号一键登录(小程序原生代码实现)
版权归原作者 学习者小陈 所有, 如有侵权,请联系我们删除。