微信授权获取用户openId等信息 - 欧阳飞雪
在我们开发小程序的时候,需要通过授权获取用户的信息。
第一种使用wx.getUserInfo直接获取微信头像,昵称
// 必须是在用户已经授权的情况下调用 wx.getUserInfo({ success: function(res) { var userInfo = res.userInfo var nickName = userInfo.nickName var avatarUrl = userInfo.avatarUrl var gender = userInfo.gender //性别 0:未知、1:男、2:女 var province = userInfo.province var city = userInfo.city var country = userInfo.country } })
第二种方式使用wx.login()
这种方式即将被放弃,目前使用比较多的是的wx.login()。因为直接使用wx.getUserInfo是不能获取更多的信息的,如微信用户的openid。 官方提示,需要发送获取到的code进行请求到微信的后端API。根据文档,只需要进行一个get请求到如下地址即可:
https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_codeappid和secret在微信小程序后台可以看到,
js_code为使用wx.login登录时获取到的code参数数据,grant_type这个不用改动。
官方推荐
在login获取到code,然后发送到开发者后端,后端再通过接口去微信后端换取到openid和sessionKey之后,然后把session返回给前端,就已经完成登录行为。而login行为是静默,不必授权的,不会对用户造成骚扰。getUserInfo只是为了提供更优质的服务而存在,比如展示头像昵称,判断性别,通过unionId和其他公众号上已有的用户画像结合起来提供历史数据。所以不必在刚刚进入小程序的时候就强制要求授权。相关代码如下所示。
JS代码 var userInfo= (wx.getStorageSync(\'userInfo\')) if (userInfo) { wx.getUserInfo({ success: function (res) { that.setData({ nickName: res.userInfo.nickName, avatarUrl: res.userInfo.avatarUrl, }) }, fail: function () { console.log("获取失败!") }, complete: function () { console.log("获取用户信息完成!") } }) } else { wx.login({ success: function (res) { console.log(res.code) if (res.code) { wx.getUserInfo({ withCredentials: true, success: function (res_user) { wx.request({ //后台接口地址 url: \'https://xxxx.com/wx/login\', data: { code: res.code }, method: \'GET\', header: { \'content-type\': \'application/json\' }, success: function (res) { that.setData({ userInfo: res.errMsg.userInfo }) wx.setStorageSync(\'userInfo\', res.data.userInfo); } }) }, fail: function () { wx.showModal({ title: \'警告通知\', content: \'您点击了拒绝授权,将无法正常显示个人信息,点击确定重新获取授权。\', success: function (res) { if (res.confirm) { wx.openSetting({ success: (res) => { if (res.authSetting["scope.userInfo"]) {////如果用户重新同意了授权登录 wx.login({ success: function (res_login) { if (res_login.code) { wx.getUserInfo({ withCredentials: true, success: function (res_user) { wx.request({ url: \'https://xxxx.com/wx/login\', data: { code: res_login.code }, method: \'GET\', header: { \'content-type\': \'application/json\' }, success: function (res) { that.setData({ userInfo: res.errMsg.userInfo }) wx.setStorageSync(\'userInfo\', res.errMsg.userInfo); } }) } }) } } }); } }, fail: function (res) { } }) } } }) }, complete: function (res) { } }) } } }) } }, //globalData建议放在app.js,方便统一管理 globalData: { userInfo: null }
后端代码
由于我的后端是PHP写的,用的是thinkphp5框架,框架地址:https://www.kancloud.cn/manual/thinkphp5/118003
/** * 小程序登录 * @return array */ public function login() { $code = input(\'post.code\'); //这是从前端传过来的code $userInfo = input(\'post.userInfo\'); $info = json_decode($userInfo, true); $user = $info[\'userInfo\']; $memberModel = model(\'Member\'); $appid = "小程序的appid"; //一定要是小程序的appid,不是微信公众号的appid $secret = "小程序的secret"; $url = "https://api.weixin.qq.com/sns/jscode2session?appid=". $appid."&secret=".$secret."&js_code=" . $code . "&grant_type=authorization_code"; //初始化curl $ch = curl_init($url); //3.设置参数 curl_setopt($ch,CURLOPT_RETURNTRANSFER,1); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);//跳过证书验证 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // 从证书中检查SSL加密算法是否存在 $res = curl_exec($ch); if(curl_errno($ch)){ var_dump(curl_error($ch)); } $resArr = json_decode($res,1); $data = array(); curl_close($ch); $mapData = array(); //这里我把用户的信息保存起来,方便下次调用,数据库结构我们在下面会介绍 if (!empty($resArr[\'openid\'])) { $res = $memberModel->checkMember($resArr[\'openid\']); Log::write(\'用户信息:\' . $memberModel->getLastSql()); if ($res) { $mapData[\'userInfo\'] = $res; $mapData[\'session_key\'] = $resArr[\'session_key\']; return $this->resMap(200, $mapData, $mapData); } else { $data[\'nickName\'] = $user[\'nickName\']; $data[\'avatarUrl\'] = $user[\'avatarUrl\']; $data[\'m_province\'] = $user[\'province\']; $data[\'m_city\'] = $user[\'city\']; $data[\'m_gender\'] = $user[\'gender\']; $data[\'m_language\'] = $user[\'language\']; $data[\'signature\'] = $info[\'signature\']; $data[\'iv\'] = $info[\'iv\']; $data[\'m_uuid\'] = showUuid(); $data[\'m_openid\'] = $resArr[\'openid\']; $data[\'m_country\'] = $resArr[\'country\']; $data[\'m_ip\'] = GetIP(); $data[\'m_createtime\'] = getDateTime(1); $memberModel->addOne($data); $mapData[\'userInfo\'] = $data; $mapData[\'session_key\'] = $resArr[\'session_key\']; return $this->resMap(200, $mapData, $mapData); } } else { return $this->resMap(4002, \'登录失败\', \'登录失败\'); } } /** * 返回提示信息 * @param $code string 错误码 4001 空值 4002 格式不正确 4003 长度 4004 提示 200正确放回 ,0失败 * @param $msg string 错误描述 * @param $data string 返回值 * @return array */ public function resMap($code, $msg, $data) { $map = array(); $map[\'errMsg\'] = $msg; $map[\'data\'] = $data; $map[\'errCode\'] = $code; return json($map); }
以上就是核心代码,希望对大家有用。在上面,我们需要保存用户的信息,因此我们需要数据库表,下面就谈到表的设计。
用户表的设计
SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for `system_member` -- ---------------------------- DROP TABLE IF EXISTS `system_member`; CREATE TABLE `system_member` ( `m_id` INT(11) NOT NULL AUTO_INCREMENT, `nickName` VARCHAR(50) DEFAULT NULL COMMENT \'用户昵称\', `avatarUrl` VARCHAR(255) DEFAULT NULL COMMENT \'头像\', `m_province` VARCHAR(40) DEFAULT NULL COMMENT \'省份\', `m_city` VARCHAR(50) DEFAULT NULL COMMENT \'城市\', `m_name` VARCHAR(30) DEFAULT NULL COMMENT \'真实姓名\', `m_gender` TINYINT(1) DEFAULT \'3\' COMMENT \'用户性别(1、男 2、女 3、未知)\', `m_createtime` DATETIME DEFAULT NULL COMMENT \'创建时间\', `m_country` VARCHAR(100) DEFAULT NULL COMMENT \'国家\', `m_language` VARCHAR(50) DEFAULT NULL COMMENT \'语言\', `m_openid` VARCHAR(50) DEFAULT NULL COMMENT \'openID\', `m_ip` VARCHAR(15) DEFAULT NULL COMMENT \'IP\', `m_mobile` VARCHAR(20) DEFAULT NULL COMMENT \'手机号码\', `m_uuid` VARCHAR(50) DEFAULT NULL, `m_username` VARCHAR(50) DEFAULT NULL COMMENT \'用户名\', `m_pwd` VARCHAR(50) DEFAULT NULL COMMENT \'密码\', `session_key` VARCHAR(255) DEFAULT NULL COMMENT \'会话密钥\', `unionid` VARCHAR(255) DEFAULT NULL COMMENT \'用户在开放平台的唯一标识符\', `signature` VARCHAR(255) DEFAULT NULL, `iv` VARCHAR(255) DEFAULT NULL, `k_id` VARCHAR(50) DEFAULT NULL, `k_openid` VARCHAR(80) DEFAULT NULL, PRIMARY KEY (`m_id`) ) ENGINE=INNODB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8 COMMENT=\'获取用户小程序信息\';
以上就是获取用户信息的完整流程,下面我们附上一张用户登录的流程图。
如果大家有什么不明白的地方,可以加入我们的微信交流群:731568857,里面有很多技术资源。或者关注我们的微信公众号。
JS代码var userInfo= (wx.getStorageSync(\’userInfo\’)) if (userInfo) { wx.getUserInfo({ success: function (res) { that.setData({ nickName: res.userInfo.nickName, avatarUrl: res.userInfo.avatarUrl, }) }, fail: function () { console.log(“获取失败!”) }, complete: function () { console.log(“获取用户信息完成!”) } }) } else { wx.login({ success: function (res) { console.log(res.code) if (res.code) { wx.getUserInfo({ withCredentials: true, success: function (res_user) { wx.request({ //后台接口地址 url: \’https://xxxx.com/wx/login\’, data: { code: res.code }, method: \’GET\’, header: { \’content-type\’: \’application/json\’ }, success: function (res) { that.setData({ userInfo: res.errMsg.userInfo }) wx.setStorageSync(\’userInfo\’, res.data.userInfo);
} }) }, fail: function () { wx.showModal({ title: \’警告通知\’, content: \’您点击了拒绝授权,将无法正常显示个人信息,点击确定重新获取授权。\’, success: function (res) { if (res.confirm) { wx.openSetting({ success: (res) => { if (res.authSetting[“scope.userInfo”]) {////如果用户重新同意了授权登录 wx.login({ success: function (res_login) { if (res_login.code) { wx.getUserInfo({ withCredentials: true, success: function (res_user) { wx.request({ url: \’https://xxxx.com/wx/login\’, data: { code: res_login.code }, method: \’GET\’, header: { \’content-type\’: \’application/json\’ }, success: function (res) { that.setData({ userInfo: res.errMsg.userInfo
}) wx.setStorageSync(\’userInfo\’, res.errMsg.userInfo); } }) } }) } } }); } }, fail: function (res) {
} })
} } }) }, complete: function (res) {
} }) } } })
} },//globalData建议放在app.js,方便统一管理 globalData: { userInfo: null }