在我们日常开发微信小程序的过程中,难免会遇到小程序登录功能,以下是我的解决方案
注意:微信登录的code和手机号快速登录的code是不一样的
一、前端开发
前端开发我使用的是uniapp,代码如下
template部分:
<!-- #ifdef MP-WEIXIN -->
<button type="primary" size="mini" v-if="!isLogin" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">手机号一键登录</button>
<!-- #endif -->
script部分:
// 手机号登录
const getPhoneNumber = async (e) => {if(e.detail.code == undefined) {return}else{uni.login({provider:"weixin",success:res=>{login(res.code, e.detail.code)}})}
}// 登录
const login = async (code, p_cpde) => {const res = await axios.post(`/login?code=${code}&p_code=${p_cpde}`)console.log(res)userInfo.value = res.data.data.userisLogin.value = true// 将信息存入本地uni.setStorageSync("token",res.data.data.token)uni.setStorageSync("user",res.data.data.user)Notify({ type: 'success', message: '登录成功!' });
}
二、后端开发
后端开发我使用的是SpringBoot+MyBatis+MyBatisPlus
其中,需要添加的几个重要依赖:
<dependency><groupId>net.minidev</groupId><artifactId>json-smart</artifactId><version>2.4.8</version><scope>compile</scope>
</dependency>
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-annotations</artifactId><version>2.13.4</version>
</dependency>
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version>
</dependency>
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.72</version>
</dependency>
<dependency><groupId>org.json</groupId><artifactId>json</artifactId><version>20210307</version>
</dependency><!-- 微信-->
<dependency><groupId>com.github.binarywang</groupId><artifactId>weixin-java-miniapp</artifactId><version>4.5.9.B</version>
</dependency>
接口开发:
controller:
@RestController
public class LoginController {@Resourceprivate LoginService loginService;@PostMapping("/login")public Result login(@Param("code") String code,@Param("p_code")String p_code) {return loginService.login(code, p_code);}}
service:
public interface LoginService {
// 小程序一键登录Result login(String code,String p_code);}
serviceImpl:
@Service
public class LoginServiceImpl implements LoginService {private static final String APPID = "";private static final String SECRET = "";@Resourceprivate MiniUserMapper miniUserMapper;@Overridepublic Result login(String code, String p_code) {String userPhone = "";
// 判断用户是否授权if (code != null) {userPhone = getUserPhone(p_code);}HashMap<String, Object> map = new HashMap<>();
// 将code发送到微信服务器进行登录凭证校验String url = "https://api.weixin.qq.com/sns/jscode2session?appid={0}&secret={1}&js_code={2}&grant_type=authorization_code";String replaceUrl = url.replace("{0}", APPID).replace("{1}", SECRET).replace("{2}", code);String res = HttpUtil.get(replaceUrl);// 从微信服务器返回的数据中提取 openid 和 session_key// 解析JSON数据org.json.JSONObject jsonObject = new JSONObject(res);// 提取openidString openid = jsonObject.getString("openid");
// 判断判断数据库中是否有该openid记录,有则查询信息返回数据,没有则注册并返回数据QueryWrapper<MiniUser> userQueryWrapper = new QueryWrapper<>();userQueryWrapper.eq("open_id", openid);MiniUser miniUser = miniUserMapper.selectOne(userQueryWrapper);
// 判断if (miniUser == null){// 生成随机6个字符String randomStr = new Random().ints('A', 'Z' + 1) // 生成'A'到'Z'之间的随机整数流.limit(6) // 限制生成6个字符.collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append).toString();miniUser = new MiniUser();miniUser.setOpenId(openid);miniUser.setName("姓名_"+ randomStr);miniUser.setPhone(userPhone);miniUserMapper.insert(miniUser);String token = JWTUtils.generateToken(openid);map.put("token", token);map.put("user", miniUser);return Result.success("登录成功", map);}if (miniUser != null) {String token = JWTUtils.generateToken(miniUser.getOpenId());map.put("token", token);map.put("user", miniUser);return Result.success("登录成功", map);}return Result.fail("登录失败");}public String getUserPhone(String code) {String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}&";String replaceUrl = url.replace("{0}", APPID).replace("{1}", SECRET);String res = HttpUtil.get(replaceUrl);org.json.JSONObject jsonObject = new JSONObject(res);// 提取access_tokenString access_token = jsonObject.getString("access_token");
// 获取手机号String url1 = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token={0}";String replaceUrl1 = url1.replace("{0}", access_token);JSONObject params = new JSONObject();params.put("code", code);String res1 = HttpUtil.post(replaceUrl1, params.toString());JSONObject response = new JSONObject(res1);// 提取 phone_infoJSONObject phoneInfo = response.getJSONObject("phone_info");String phoneNumber = phoneInfo.getString("phoneNumber");return phoneNumber;}
}
实体:MiniUser
@AllArgsConstructor
@NoArgsConstructor
@Data
@TableName("mini_user")
public class MiniUser {@TableId(value = "mini_user_id",type = IdType.AUTO)private Integer miniUserId;// 用户idprivate String openId;// openIdprivate String name; // 姓名private String phone;// 手机号private String password; // 密码private String createTime; // 创建时间private String updateTime; // 更新时间private Integer status; // 状态(1-正常、2-冻结)}
mapper:MiniUserMapper
public interface MiniUserMapper extends BaseMapper<MiniUser> {}