uniapp实现小程序登录(支持手机号授权登录)
第一步.前端处理
页面登录按钮
<!--第一种:手机号授权登录-->
<button size="lg" class="white br60 row-center btn" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">
<image class="mr10 image" src="/static/images/icon_wechat.png"></image>
<text>微信一键授权</text>
</button>
<!-- 第二种:微信用户授权登录 -->
<!-- <button size="lg" class="white br60 row-center btn" @click="mnpLoginFun">
<image class="mr10 image" src="/static/images/icon_wechat.png"></image>
<text>微信授权登录</text>
</button> -->
js函数,调用后台接口,实现登录
import { getWxCode } from '@/utils/login';
methods: {
//...mapMutations(['LOGIN']),
//小程序微信手机号授权登录
async getPhoneNumber(e) {
if (e.detail.errMsg == 'getPhoneNumber:fail user deny') {
console.log('用户拒绝提供手机号');
} else {
uni.showLoading({
title: '登录中...',
mask: true
});
const wxCode = await getWxCode();
uni.request({
url: baseURL + '/mobile-api/wechat/getWxOpenIdAndSkey',
header: {
'content-type': 'application/x-www-form-urlencoded'
},
method: 'POST',
data: {
code: wxCode,
encryptedData: e.detail.encryptedData,
iv: e.detail.iv
},
success: res => {
//登录成功后,业务处理
console.log("res::",res)
if(res.data.code == 1) {
//前端处理用户登录信息
this.loginHandle(res.data.data)
//登录成功跳转页面
uni.switchTab({
url:"/pages/index/index"
})
}else {
this.$toast({
title: "服务异常"
})
}
}
});
}
},
//小程序微信用户授权登录
async mnpLoginFun() {
const userInfo = await getUserProfile();
console.log(userInfo, 'userInfo');
uni.showLoading({
title: '登录中...',
mask: true
});
const wxCode = await getWxCode();
uni.request({
url: baseURL + '/mobile-api/wechat/getWxOpenIdAndSkey',
header: {
'content-type': 'application/x-www-form-urlencoded'
},
method: 'POST',
data: {
code: wxCode,
encryptedData: userInfo.encryptedData,
iv: userInfo.iv
},
success: res => {
if(res.data.code == 1) {
this.loginHandle(res.data.data)
uni.switchTab({
url:"/pages/index/index"
})
}else {
this.$toast({
title: "服务异常"
})
}
}
});
},
// 登录结果处理
async loginHandle(data) {
//this.LOGIN(data);
uni.hideLoading();
}
js函数,获取登录凭证(code), 本例文件目录 /utils/login.js
// 获取登录凭证(code)
export function getWxCode() {
return new Promise((resolve, reject) => {
uni.login({
provider: 'weixin',
success(res) {
resolve(res.code);
},
fail(res) {
reject(res);
}
});
});
}
拓展,可忽略:import Cache from '@/utils/cache';
const Cache = {
//设置缓存(expire为缓存时效)
set(key, value, expire) {
let data = {
expire: expire ? (this.time() + expire) : "",
value
}
console.log(data, key)
if (typeof data === 'object')
data = JSON.stringify(data);
try {
uni.setStorageSync(key, data)
} catch (e) {
return false;
}
},
get(key) {
try {
let data = uni.getStorageSync(key)
const {value, expire} = JSON.parse(data)
if(expire && expire < this.time()) {
uni.removeStorageSync(key)
return false;
}else {
return value
}
} catch (e) {
return false;
}
},
//获取当前时间
time() {
return Math.round(new Date() / 1000);
},
remove(key) {
if(key) uni.removeStorageSync(key)
}
}
export default Cache;
第二步.Java后端处理
登录接口,入口
@RequestMapping(value = "getWxOpenIdAndSkey",method = RequestMethod.POST)
public Object getWxOpenIdAndSkey(String code, String iv,String encryptedData, HttpServletRequest request) {
try{
Map<String,Object> map = weixinService.getWxOpenIdAndSkey(code);
String openid = map.get("openid").toString();
ShopUser user = shopUserService.findByWechatOpenId(openid);
JSONObject obj = getUserInfo(encryptedData, map.get("session_key").toString(), iv);
if(obj!=null){
if(obj.containsKey("avatarUrl")) {
//获取头像
}
if(obj.containsKey("nickName")) {
//获取昵称
}
//性别 0:未知、1:男、2:女
if(obj.containsKey("gender")){
//获取性别
}
if(obj.containsKey("phoneNumber")){
//获取手机号
//user.setMobile(obj.getString("phoneNumber"));
}
}
//user是用户信息接收对象,这里省略,你你懂得。。
// map.put("user", user);
return Json.toJson(map);
}catch (Exception e){
logger.info("{}:解析用户信息异常",e);
return Rets.failure( e.getMessage());
}
}
WeixinService.java(文件内容仅保留微信相关,配置参数取与数据库后台配置,这里省略)
package cn.enilu.flash.service.api;
import cn.enilu.flash.bean.constant.CfgKey;
import cn.enilu.flash.bean.entity.shop.ShopUser;
import cn.enilu.flash.bean.entity.system.Cfg;
import cn.enilu.flash.bean.exception.ApplicationException;
import cn.enilu.flash.bean.exception.ApplicationExceptionEnum;
import cn.enilu.flash.bean.vo.shop.WechatInfo;
import cn.enilu.flash.cache.CacheDao;
import cn.enilu.flash.service.shop.ShopUserService;
import cn.enilu.flash.service.system.CfgService;
import cn.enilu.flash.utils.HttpUtil;
import cn.enilu.flash.utils.Maps;
import cn.enilu.flash.utils.StringUtil;
import org.json.JSONObject;
import org.nutz.http.Http;
import org.nutz.json.Json;
import org.nutz.mapl.Mapl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* @author :wt
* @date :Created in 1/19/2020 4:31 PM
*/
@Service
public class WeixinService {
@Autowired
private CfgService cfgService;
@Autowired
private ShopUserService shopUserService;
@Autowired
private CacheDao cacheDao;
private Logger logger = LoggerFactory.getLogger(WeixinService.class);
public String getAccessToken() {
String appId = cfgService.getCfgValue(CfgKey.WX_APP_ID);
String appSecret = cfgService.getCfgValue(CfgKey.WX_APP_SECRET);
String accessTokenUrl = cfgService.getCfgValue(CfgKey.WX_ACCESS_TOKEN_URL);
String url = String.format(accessTokenUrl, appId, appSecret);
String result = Http.get(url).getContent();
logger.info("获取微信token,\r\nurl : {},\r\n result : {}", url, result);
Object object = Json.fromJson(StringUtil.sNull(result));
String access_token = (String) Mapl.cell(object, "access_token");
return access_token;
}
public Map<String, Object> getPrivateAccessToken(String code) {
String url = "https://api.weixin.qq.com/sns/jscode2session";
url += "?appid=" + cfgService.getCfgValue(CfgKey.WX_APP_ID);
url += "&secret=" + cfgService.getCfgValue(CfgKey.WX_APP_SECRET);
url += "&js_code=" + code;
url += "&grant_type=authorization_code";
try {
String result = Http.get(url).getContent();
Object object = Json.fromJson(StringUtil.sNull(result));
logger.info("url:" + url + "; response:" + Json.toJson(object));
//access_token
String access_token = (String) Mapl.cell(object, "session_key");
if (StringUtil.isNotEmpty(access_token)) {
return (Map) object;
}
} catch (Exception e) {
logger.error("获取token失败", e);
}
return null;
}
public WechatInfo getWechatInfoByCode(String code) {
Map<String, Object> ret = getPrivateAccessToken(code);
logger.info("获取token:{}", Json.toJson(ret));
if (ret != null && ret.get("errcode") == null) {
String openId = StringUtil.sNull(ret.get("openid"));
return getWechatInfo(openId);
}
return null;
}
//https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s
public WechatInfo getWechatInfo(String openId) {
String accessToken = cfgService.getCfgValue(CfgKey.WX_ACCESS_TOKEN);
String url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + accessToken + "&openid=" + openId;
String result = Http.get(url).getContent();
Object object = Json.fromJson(StringUtil.sNull(result));
logger.info("getWecchatInfo====url:" + url + "; response:" + Json.toJson(object));
if (Mapl.cell(object, "errcode") != null) {
logger.info("获取微信用户基本信息失败", Mapl.cell(object, "errmsg"));
if(Mapl.cell(object, "errcode").toString().equals("40001")){
updateWeixinToken();
getWechatInfo(openId);
}
} else {
if (StringUtil.equals(StringUtil.sNull(Mapl.cell(object, "errcode")), "0")) {
logger.error("用户:{}没有关注该公众号", openId);
} else {
WechatInfo wechatInfo = new WechatInfo();
wechatInfo.setOpenId(openId);
wechatInfo.setNickName(StringUtil.sNull(Mapl.cell(object, "nickname")));
wechatInfo.setHeadUrl(StringUtil.sNull(Mapl.cell(object, "headimgurl")));
return wechatInfo;
}
}
return null;
}
private String createNonceStr() {
return UUID.randomUUID().toString();
}
private String createTimestamp() {
return Long.toString(System.currentTimeMillis() / 1000);
}
private String byteToHex(final byte[] hash) {
Formatter formatter = new Formatter();
for (byte b : hash) {
formatter.format("%02x", b);
}
String result = formatter.toString();
formatter.close();
return result;
}
public Map<String, String> getSign(String url) {
Map<String, String> map = getSign(cfgService.getCfgValue(CfgKey.WX_JS_API_TICKET), url);
map.put("appId", cfgService.getCfgValue(CfgKey.WX_APP_ID));
return map;
}
public Map<String, String> getSign(String jsapi_ticket, String url) {
Map<String, String> ret = new HashMap<String, String>();
String nonce_str = createNonceStr();
String timestamp = createTimestamp();
String string1;
String signature = "";
// 注意这里参数名必须全部小写,且必须有序
string1 = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonce_str + "×tamp=" + timestamp + "&url=" + url;
logger.info(string1);
try {
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(string1.getBytes("UTF-8"));
signature = byteToHex(crypt.digest());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
ret.put("url", url);
ret.put("jsapi_ticket", jsapi_ticket);
ret.put("nonceStr", nonce_str);
ret.put("timestamp", timestamp);
ret.put("signature", signature);
return ret;
}
public Map<String, Object> getWxOpenIdAndSkey(String code) {
Map<String, Object> map = getPrivateAccessToken(code);
map.put("code",1);//自定义登录成功状态
//return Json.toJson(map);
return map;
}
}
通过以上步骤,可满足用户微信小程的登录,包括手机号授权登录,并获取用户详细登录信息.
有疑问的地方,欢迎大家给我留言,一起交流哦~
1、所有文章未经授权禁止转载、摘编、复制或建立镜像,如有违反,追究法律责任。
2、本站文章部分来源注册用户发布或互联网收集而来,若有侵权,请邮件联系作者。
邮箱地址:wtao219@qq.com
2、本站文章部分来源注册用户发布或互联网收集而来,若有侵权,请邮件联系作者。
邮箱地址:wtao219@qq.com
THE END
二维码