首先去微信官方文档可以看到获取手机号的接口需要用到token权限。因此我们需要先拿到token。
在获取个人信息授权时候可以直接在前端调用getUserProfile方法
getUserProfile : function(){
uni.getUserProfile({
desc:'用于测试开发',
success:function(infoRes){
console.log(infoRes)
},
fail : function(err){
console.log(err);
}
})
}
在开发工具中点击按钮可以看到开始拉取授权,需要主要的是,getUserProfile方法是一定要在用户参与操作下才能启用的,否则该方法无法被调用。
然后我们尝试获取手机号,需要用到open-type="getPhoneNumber" @getphonenumber="getTel"
其中getPhoneNumber是官方给我们封装好的函数,getTel是我自己随意写的方法名open-type则是微信开放能力的固定写法。
getTel : function(res){
console.log(res);
let code = res.detail.code;
console.log(res.detail.code);
uni.request({
url:"http://localhost:8080/wx/phone?code="+code,
data:{},
success: (res) => {
console.log("取电话")
console.log(res)
}
})
}
函数体中可以通过res.detail.code获取后端调用手机号接口所需要的code。
前端代码块:
<template>
<view class="content">
<image class="logo" src="/static/logo.png"></image>
<view class="text-area">
<text class="title">{{title}}</text>
</view>
<button @click="getUserProfile" open-type="getPhoneNumber" @getphonenumber="getTel">开始体验</button>
</view>
</template>
<script>
export default {
data() {
return {
title: 'Hello'
}
},
onLoad() {
uni.login({
provider: 'weixin',
success: function (loginRes) {
uni.request({
url: 'http://localhost:8080/wx/code?code='+ loginRes.code,
data: {},
success: (res) => {
}
});
}
});
},
methods: {
getUserProfile : function(){
uni.getUserProfile({
desc:'用于开发测试',
success:function(infoRes){
console.log(infoRes)
},
fail : function(err){
console.log(err);
}
})
},
getTel : function(res){
console.log(res);
let code = res.detail.code;
console.log(res.detail.code);
uni.request({
url:"http://localhost:8080/wx/phone?code="+code,
data:{},
success: (res) => {
console.log("取电话")
console.log(res)
}
})
}
}
}
</script>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.logo {
height: 200rpx;
width: 200rpx;
margin-top: 200rpx;
margin-left: auto;
margin-right: auto;
margin-bottom: 50rpx;
}
.text-area {
display: flex;
justify-content: center;
}
.title {
font-size: 36rpx;
color: #8f8f94;
}
</style>
后端首先新建一个Util类构造获取token的方法,这里我们使用同步锁以应对高并发,保障线程安全。并使用双重校验,保证运行过程中不会出现因系统编译排序导致的逻辑问题(概率极低,相当于一个人一辈子被雷劈中十次)
@Component
public class WXUtil {
String appId = "这里是APPID";
String secret = "这里是小程序秘钥";
String accessToken = "";
LocalDateTime passTime = null;
@Autowired
RestTemplate restTemplate;
public String getAccessToken() {
LocalDateTime current = LocalDateTime.now();
//同步锁,使用当前对象作为锁头(spring中bean的声明周期默认单例,可以配置,request、session)
//第一次校验:如果一个对象抢到锁头。
if (StringUtils.isEmpty(this.accessToken) || null == passTime || current.isAfter(passTime)) {
synchronized (this) {
//双重校验,第二次校验
//预防代码编译顺序被打乱。
if (StringUtils.isEmpty(this.accessToken) || null == passTime || current.isAfter(passTime)) {
//申请获取token
String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appId
+ "&secret=" + secret;
ResponseEntity<JSONObject> wxResult = restTemplate.getForEntity(url, JSONObject.class);
this.accessToken = wxResult.getBody().getString("access_token");
Long expiresIn = wxResult.getBody().getLong("expires_in");
passTime = current.plusSeconds(expiresIn);
}
}
}
return this.accessToken;
}
}
然后在获取到token后发送请求,获取到手机号信息。
@RestController
@RequestMapping("/wx")
public class WxSystemController {
String appId = "这里是APPID";
String secret = "这里是小程序秘钥";
@Autowired
RestTemplate restTemplate;
@Autowired
IUserService IUserService;
@Autowired
WXUtil wxutil;//将util文件注入进来
@GetMapping("/code")
public JSONObject code(String code) {
JSONObject result = new JSONObject();
// 向微信发请求 获取onenId
String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appId + "&secret=" + secret + "&js_code="
+ code + "&grant_type=authorization_code";
// 发送HTTP请求
ResponseEntity<String> wxResult = restTemplate.getForEntity(url, String.class);
// 把String转换成JSON
JSONObject wxJsonObject = JSONObject.parseObject(wxResult.getBody());
// 获取openId
String openId = wxJsonObject.getString("openid");
QueryWrapper<User> ifOppenIdqueryWaQueryWrapper = new QueryWrapper<>();
ifOppenIdqueryWaQueryWrapper.eq("openId", openId);
List<User> userList = IUserService.list(ifOppenIdqueryWaQueryWrapper);
if (0 == userList.size()) {
result.put("result", false);
return result;
} else {
result.put("result", true);
return result;
}
}
@GetMapping("/phone")
public JSONObject Phone(String code) {
String accessToken = wxutil.getAccessToken();
String url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + accessToken;
Map<String, Object> requestParam = new HashMap<String, Object>();
requestParam.put("code", code);
ResponseEntity<JSONObject> wxResult = restTemplate.postForEntity(url, requestParam, JSONObject.class);
JSONObject phoneInfo = wxResult.getBody().getJSONObject("phone_info");
return phoneInfo;
}
}
运行后可在微信开发者工具上打印出结果: