在我们日常开发微信小程序的过程中,难免会遇到小程序登录功能,以下是我的解决方案
注意:微信登录的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.user
isLogin.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 {
@Resource
private 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 = "";
@Resource
private MiniUserMapper miniUserMapper;
@Override
public 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);
// 提取openid
String 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_token
String 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_info
JSONObject 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;// 用户id
private String openId;// openId
private 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> {}