微信小程序–登录+获取用户信息+获取手机号+获取位置信息
主题部分
1、登录基础代码
wxml:
<view class="userinfo" style="margin-bottom:50rpx">
<view class="userinfo" style="margin-top:45%">
<button wx:if="{ {hasUserInfo==1}}" open-type="getUserInfo" bindgetuserinfo="getUserInfo">
登录
</button>
</view>
<block wx:if="{ {hasUserInfo==2}}">
<image class="userinfo-avatar" src="{ {userInfo.avatarUrl}}" mode="cover"></image>
<text class="userinfo-nickname">{
{userInfo.nickName}}</text>
</block>
</view>
js:
getUserInfo: function (e) {
console.log("-=-=-=-=-=-=-=-=-=")
console.log(e.detail.userInfo)
if (e.detail.userInfo){
app.globalData.userInfo = e.detail.userInfo
userInfo = e.detail.userInfo
this.setData({
userInfo: e.detail.userInfo,
hasUserInfo: 2
})
this.flush();
}else{
this.setData({
hasUserInfo: 1
})
}
}
2、根据wx.login登录获取code,根据code获取openId和sessionKey,每个人的openId都是唯一的。
js代码:
wx.login({
success: function (res) {
if (res.code) {
console.log("code------"+res.code)
//根据code获取openId, sessionKey, unionId
wx.request({
url: urlIndex+'/minicx/mini/getOpenid?code=' + res.code,
method: 'GET',
success: function (res) {
openId = res.data.openid;
sessionKey = res.data.session_key;
console.log("openId------"+openId);
console.log("sessionKey------" +sessionKey);
}
})
}
}
})
后台代码:
/** * 小程序登录接口 * @param code 用户登录凭证 * @return */
@RequestMapping("/getOpenid")
@ResponseBody
public String login(String code){
logger.debug("======小程序登录接口getOpenid=====");
String appid = PayConfigUtil.MINI_APP_ID;
String secret = PayConfigUtil.MINI_APP_SECRET;
String url = "https://api.weixin.qq.com/sns/jscode2session?appid="+appid+"&secret="+secret+"&js_code="+code+"&grant_type=authorization_code";
JSONObject json = new JSONObject();
try {
json = HttpClientUtilsmini.httpsRequest(url, "get", null);
} catch (Exception e) {
logger.error(ExceptionUtils.getStackTrace(e));
}
return json.toJSONString();
}
/** * 发起https请求并获取结果 * * @param requestUrl 请求地址 * @param requestMethod 请求方式(GET、POST) * @param submitStr 提交的json格式数据 * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值) */
public static JSONObject httpsRequest(String requestUrl, String requestMethod, String submitStr) throws Exception{
JSONObject jsonObject = null;
StringBuffer buffer = new StringBuffer();
URL url = new URL(requestUrl);
HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
httpUrlConn.setDoOutput(true);
httpUrlConn.setDoInput(true);
httpUrlConn.setUseCaches(false);
httpUrlConn.setConnectTimeout(10000);
httpUrlConn.setReadTimeout(10000);
// 设置请求方式(GET/POST)
httpUrlConn.setRequestMethod(requestMethod.toUpperCase());
if ("GET".equalsIgnoreCase(requestMethod))
httpUrlConn.connect();
// 当有数据需要提交时
if (null != submitStr) {
OutputStream outputStream = httpUrlConn.getOutputStream();
// 注意编码格式,防止中文乱码
outputStream.write(submitStr.getBytes("UTF-8"));
outputStream.close();
}
// 将返回的输入流转换成字符串
InputStream inputStream = httpUrlConn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
bufferedReader.close();
inputStreamReader.close();
// 释放资源
inputStream.close();
inputStream = null;
httpUrlConn.disconnect();
jsonObject = JSONObject.parseObject(buffer.toString());
return jsonObject;
}
3、用户授权后,获取用户加密手机号信息,根据openId和sessionKey将加密手机号解析。
wxml:
<button wx:if="{ {!phoneNum}}" open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">扫一扫</button>
<button wx:else bindtap="scanCode">扫一扫</button>
js代码:
//用户点击扫一扫
scanCode:function(){
console.log("不需要手机授权的扫一扫")
this.locationAndScanCode();
},
//用户点击扫一扫
getPhoneNumber(e){
console.log("需要手机授权的扫一扫")
var that = this;
console.log(e.detail)
console.log(e.detail.iv)
console.log(e.detail.encryptedData)
//获取用户授权店的手机号,从后台转换
wx.request({
url: urlIndex + '/minicx/mini/getPhoneNum',
method:'POST',
data:{
encrypData: e.detail.encryptedData,
ivData: e.detail.iv,
sessionKey: sessionKey
},
header: {
'content-type': 'application/x-www-form-urlencoded'
},
success:function(res){
console.log(res.data.phoneNumber);
that.setData({
phoneNum: res.data.phoneNumber
})
if (res.data.phoneNumber!=null){
//将刚获取的手机号加上openId一起传到后台保存
wx.request({
url: urlIndex + '/minicx/mini/insertPhoneNum',
method: 'POST',
data: {
openId: openId,
userPhone: res.data.phoneNumber
},
header: {
'content-type': 'application/x-www-form-urlencoded'
},
success: function (res) {
userId = res.data;
}
})
}
}
})
if (e.detail.encryptedData!=null){
this.locationAndScanCode();
}
},
java:
/** * 获取微信手机号 * @param encrypData * @param ivData * @param sessionKey * @return */
@RequestMapping(value="/getPhoneNum")
@ResponseBody
public String getPhoneNum(String encrypData,String ivData,String sessionKey){
System.out.println("----"+encrypData);
System.out.println("----"+ivData);
System.out.println("----"+sessionKey);
logger.debug("======小程序获取手机号接口getPhoneNum=====");
JSONObject json = new JSONObject();
try {
if(encrypData!=null && ivData!=null && sessionKey!=null
&& encrypData!="" && ivData!="" && sessionKey!="") {
json = miniService.getPhoneNum(encrypData, ivData, sessionKey);
}
} catch (Exception e) {
logger.error(ExceptionUtils.getStackTrace(e));
}
return json.toJSONString();
}
@Override
public JSONObject getPhoneNum(String encrypData, String ivData,String sessionKey) throws Exception {
//Thread.sleep(850);
JSONObject json = new JSONObject();
byte[] encryp = Base64.decodeBase64(encrypData);
byte[] iv= Base64.decodeBase64(ivData);
byte[] key = Base64.decodeBase64(sessionKey);
AlgorithmParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
String result = new String(cipher.doFinal(encryp),"UTF-8");
JSONObject resultJson = JSONObject.parseObject(result);
String phoneNumber = resultJson.getString("phoneNumber");
logger.info(phoneNumber);
json.put("errcode", 0);
json.put("errmsg", "ok");
json.put("phoneNumber", phoneNumber);
return json;
}
4、位置授权,获取位置信息。
js:
//位置授权+扫一扫
locationAndScanCode:function(){
//获取位置
wx.getLocation({
type: 'wgs84',
success(res) {
const latitude = res.latitude
const longitude = res.longitude
console.log("纬度:" + latitude)
console.log("经度:" + longitude)
// 允许从相机和相册扫码
wx.scanCode({
success(res) {
console.log(res.result);
if (Object.keys(res.result).length == 17) {
wx.redirectTo({
url: '../vin/vin?vinCode=' + res.result +'&userId='+userId,
})
}else{
wx.showModal({
title: '提示',
content: '扫描失败,请重新扫描!',
showCancel: false,
confirmText: '好的',
success: function (res) {
}
})
}
},
fail(res) {
console.log("扫描失败")
}
})
},
fail: function () {
wx.getSetting({
success: function (res) {
if (!res.authSetting['scope.userLocation']) {
wx.showModal({
title: '',
content: '请允许系统获取您的定位!',
confirmText: '授权',
showCancel: false,
success: function (res) {
if (res.confirm) {
wx.openSetting();
} else {
console.log('用户拒绝了位置授权。');
}
}
})
} else {
//用户已授权,但是获取地理位置失败,提示用户去系统设置中打开定位
wx.showModal({
title: 'GPS未开启',
content: '请在系统设置中打开定位服务!',
showCancel:false,
confirmText: '好的',
success: function (res) {
}
})
}
}
})
}
})
},
小坑部分
1、小程序跟后台交互时,post请求必须加上header属性,如下,否则参数传不到后台。
wx.request({
url: urlIndex + '/minicx/mini/insertPhoneNum',
method: 'POST',
data: {
openId: openId,
userPhone: res.data.phoneNumber
},
//post请求要加header,不然参数传不到后台
header: {
'content-type': 'application/x-www-form-urlencoded'
},
success: function (res) {
userId = res.data;
}
})
2、小程序只支持https请求,在本地测试时,可自行购买隧道,申请域名、证书。
链接: https://segmentfault.com/a/1190000011310292.