微信小程序中的微信登录


梳理下微信小程序中登录部分。


需求分析

在小程序中,可以拥有常规的网站手机或账户密码登录外,还有微信登录。类似摩拜单车的微信小程序就是两者共存。

20170630155226

但是无论如何,使用微信登录我认为是必须的,而常规的登录可有可无了。

我的需求:

用户点击微信登录,返回用户的登录令牌accessToken。

如果在数据库中不存在过这个微信用户,就构造用户名密码,入库。再返回登录令牌。


整体流程

1. 用户点击微信登录,用户授权后,或者基本信息以及带上服务端需要的参数信息请求服务端。

2. 服务端校验参数,请求微信的接口获取用户的唯一标识。openid或者unionid。在微信开放平台下绑定你的小程序,然后小程序和其他移动应用,网站应用一样,同一个用户登录,虽然openid不同,但是unionid一致。

3. 根据unionid判断该微信用户是否存在。不存在,构造信息入库。


具体步骤

登录事件的绑定,比如在login页面,给一个微信登录的按钮绑定一个事件。

20170630164751

方法代码:

20170630165059

其实这些微信文档里面都有的。我主要想说下一个坑。


在服务端需要对传过来的encryptedData参数进行解密。

如果传参之前做个url编码,在服务端记得urldecode解密。

微信官方提供了一个解密SDK。其中php部分居然带了BOM头。如果你的json格式返回一直被解析成字符串,而不是对象,而且你的服务器是linux。那么应该就是这个Bom头的锅了。

20170630170239

20170630170257


接口可以看文档: 小程序-登录-签名加密


服务端处理流程

AppID(小程序ID) 和 AppSecret(小程序密钥) 是已有的,从微信后台拿。

接受下参数:

$code = $_POST['code'];//用户授权码
$encryptedData = urldecode($_POST['encryptedData']);
$iv = $_POST['iv'];

用这个code去获取sessionKey

//获取sessionKey
$sessionKey_url = "https://api.weixin.qq.com/sns/jscode2session?appid=$AppId&secret=$AppSecret&js_code=$code&grant_type=authorization_code";
$res = json_decode(file_get_contents($sessionKey_url));

然后判断下返回,在接收一下sessionKey和openid(用户在当前小程序的唯一id)

$sessionKey = $res->session_key;
$openid = $res->openid;

接着引入上面的微信解码SDK,wxBizDataCrypt.php

$pc = new WXBizDataCrypt($AppId, $sessionKey);
$errCode = $pc->decryptData($encryptedData, $iv, $data);
if ($errCode == 0) {
    $data = json_decode($data);
    //对比水印中的appid
    $watermark_appid = $data->watermark->appid;
    if($AppId == $watermark_appid){
        $unionid = $data->unionId;
	$nickname = $data->nickName;//微信用户名
        $headimgurl = $data->avatarUrl;//微信用户头像
        /*unionid是微信开放平台下多应用间的用户统一标识
        后面就是根据unionid判断用户是否已存在了,
        没存在把数据入库,否则就更新用户信息。
        最后都是返回accessToken,作为用户的登录令牌。
        不了解unionid的自己搜哦*/
    }
    //失败
}else{
    //失败
}


获取用户手机号码

微信小程序文档: getPhoneNumber(OBJECT)

大体上和上面那个都差不多,就是一个获取code,然后授权后拿到数据,再对数据进行解密的过程。

我最开始做的时候,是用户授权后,我拿到了 encryptedData 和 iv 之后,再调用wx.login 得到code。

然后发起请求,通过code拿到sessionKey,同微信登录解密用户信息一样,同样的解密代码。

然后出现了偶尔解密失败的情况,问题的定位是 sessionKey 出的问题,过期或是不匹配。

注意: 你需要确保你提交的参数和你服务端接收到的参数要一致,这是前提。因为可能存在全局过滤数据,导致数据变化等情况。


这里给两种解决方案:

1. 用户登录的时候,缓存其sessionKey 。然后根据  wx.checkSession 来判断用户的登录态,过期的话,则需要重新调用,wx.login拿最新的code。

如果服务端接收到了code,则根据code重新去获取sessionKey,并更新缓存,否则直接使用缓存的sessionKey


2. 在getPhoneNumber API 调用前,先调用 wx.login 获取code

我使用了这种方式,在个人中心页面onShow的时候,先调用wx.login,得到code并存起来,后面发起拿手机号授权的时候带上code就是了。(这些步骤可以做的更精致一点)


php wechat


上一篇:微信小程序POST请求无法带上参数

隐藏nginx和php的版本信息:下一篇