第三方登陆模块使开发者能快捷灵活的拥有本身的用户系统,是 LeanCloud 最受欢迎的功能之一。随着第三方平台的演化,特别是微信小程序的流行,LeanCloud 第三方登陆模块也一直在改进:html
这两个功能各自都很是简单可靠,可是其中重叠的部分需求倒是一个难题:「如何在小程序中支持 unionid 登陆,既能获得 unionid 登陆机制的灵活性,又保留一键登陆功能的便利性」。小程序
在最近发布的 JavaScript SDK v3.13 中包含了微信小程序 unionid 登陆支持。咱们根据不一样的需求设计了不一样的解决方案。后端
*这里的版本指开始支持该功能的 JavaScript SDK 版本。微信小程序
LeanCloud 的用户系统支持一键使用微信用户身份登陆。要使用一键登陆功能,须要先设置小程序的 AppID 与 AppSecret:api
1.登陆 微信公众平台,在 设置 > 开发设置 中得到 AppID 与 AppSecret。
前往 LeanCloud 控制台 > 组件 > 社交,保存「微信小程序」的 AppID 与 AppSecret。
这样你就能够在应用中使用 AV.User.loginWithWeapp()
方法来使用当前用户身份登陆了。微信
AV.User.loginWithWeapp().then(user => { this.globalData.user = user; }).catch(console.error);
使用一键登陆方式登陆时,LeanCloud 会将该用户的小程序 openid
与 session_key
等信息保存在对应的 user.authData.lc_weapp
属性中,你能够在控制台的 _User
表中看到:session
{ "authData": { "lc_weapp": { "session_key": "2zIDoEEUhkb0B5pUTzsLVg==", "expires_in": 7200, "openid": "obznq0GuHPxdRYaaDkPOHk785DuA" } } }
若是用户是第一次使用此应用,调用登陆 API 会建立一个新的用户,你能够在 控制台 > 存储 中的 _User
表中看到该用户的信息,若是用户曾经使用该方式登陆过此应用(存在对应 openid 的用户),再次调用登陆 API 会返回同一个用户。微信开发
用户的登陆状态会保存在客户端中,可使用 AV.User.current()
方法来获取当前登陆的用户,下面的例子展现了如何为登陆用户保存额外的信息:app
// 假设已经经过 AV.User.loginWithWeapp() 登陆 // 得到当前登陆用户 const user = AV.User.current(); // 调用小程序 API,获得用户信息 wx.getUserInfo({ success: ({userInfo}) => { // 更新当前用户的信息 user.set(userInfo).save().then(user => { // 成功,此时可在控制台中看到更新后的用户信息 this.globalData.user = user; }).catch(console.error); } });
authData
默认只有对应用户可见,开发者可使用 masterKey 在云引擎中获取该用户的 openid
与 session_key
进行支付、推送等操做。详情的示例请参考 支付。微信公众平台
小程序的登陆态(session_key
)存在有效期,能够经过 wx.checkSession() 方法检测当前用户登陆态是否有效,失效后能够经过调用AV.User.loginWithWeapp()
从新登陆。
微信开放平台使用 unionid 来区分用户的惟一性,也就是说同一个微信开放平台账号下的移动应用、网站应用和公众账号(包括小程序),用户的 unionid 都是同一个,而 openid 会是多个。若是你想要实现多个小程序之间,或者小程序与使用微信开放平台登陆的应用之间共享用户系统的话,则须要使用 unionid 登陆。
要在小程序中使用 unionid 登陆,请先确认已经在 微信开放平台 绑定了该小程序
在小程序中有不少途径能够 获取到 unionid。不一样的 unionid 获取方式,接入 LeanCloud 用户系统的方式也有所不一样。
当知足如下条件时,一键登陆 API AV.User.loginWithWeapp()
能静默地获取到用户的 unionid 并用 unionid + openid 进行匹配登陆。
要启用这种方式,须要在一键登陆时指定参数 preferUnionId
为 true:
AV.User.loginWithWeapp({ preferUnionId: true, });
使用 unionid 登陆后,用户的 authData 中会增长 _weixin_unionid
一项(与 lc_weapp
平级):
{ "authData": { "lc_weapp": { "session_key": "2zIDoEEUhkb0B5pUTzsLVg==", "expires_in": 7200, "openid": "obznq0GuHPxdRYaaDkPOHk785DuA", "unionid": "ox7NLs5BlEqPS4glxqhn5kkO0UUo" }, "_weixin_unionid": { "uid": "ox7NLs5BlEqPS4glxqhn5kkO0UUo" } } }
用 unionid + openid 登陆时,会按照下面的步骤进行用户匹配:
unionid(authData._weixin_unionid.uid
)的用户,则会直接做为这个用户登陆,并将全部信息(openid
、session_key
、unionid
等)更新到该用户的 authData.lc_ewapp
中。authData.lc_weapp.openid
)的用户,则会直接做为这个用户登陆,并将全部信息(session_key
、unionid
等)更新到该用户的 authData.lc_ewapp
中,同时将 unionid
保存到 authData._weixin_unionid.uid
中。session_key
、unionid
等)更新到该用户的 authData.lc_ewapp
中,同时将 unionid
保存到 authData._weixin_unionid.uid
中。无论匹配的过程是如何的,最终登陆用户的 authData
都会是上面这种结构。
LeanTodo Demo 即是使用这种方式登陆的,若是你已经关注了其关联的公众号(搜索 AVOSCloud,或经过小程序关于页面的相关公众号连接访问),那么你在登陆后会在 LeanTodo Demo 的 设置 - 用户 页面看到当前用户的 authData
中已经绑定了 unionid。
须要注意的是:
preferUnionId
也不会使用 unionid 登陆。preferUnionId
,那么该次登陆不会使用 unionid 登陆,但仍然会将获取到的 unionid 做为通常字段写入该用户的 authData.lc_weapp
中。此时用户的 authData
会是这样的:{ "authData": { "lc_weapp": { "session_key": "2zIDoEEUhkb0B5pUTzsLVg==", "expires_in": 7200, "openid": "obznq0GuHPxdRYaaDkPOHk785DuA", "unionid": "ox7NLs5BlEqPS4glxqhn5kkO0UUo" } } }
若是开发者自行得到了用户的 unionid(例如经过解密 wx.getUserInfo 获取到的用户信息),能够在小程序中调用 AV.User.loginWithWeappWithUnionId()
投入 unionid 完成登陆受权:
AV.User.loginWithWeappWithUnionId(unionid, { asMainAccount: true }).then(console.log, console.error);
若是开发者但愿更灵活的控制小程序的登陆流程,也能够自行在服务端实现 unionid 与 openid 的获取,而后调用通用的第三方 unionid 登陆接口指定平台为 lc_weapp
来登陆:
const unionid = ''; const authData = { openid: '', session_key: '' }; const platform = 'lc_weapp'; AV.User.loginWithAuthDataAndUnionId(authData, platform, unionid, { asMainAccount: true }).then(console.log, console.error);
相对上面提到的一些 Weapp 相关的登陆 API,loginWithAuthDataAndUnionId 是更加底层的第三方登陆接口,不依赖小程序运行环境,所以这种方式也提供了更高的灵活度:
AV.User.loginWithAuthDataAndUnionId
来登陆。AV.User.loginWithAuthDataAndUnionId
登陆,成功后获得登陆用户的 sessionToken
后返回给客户端,客户端再使用该 sessionToken
直接登陆。这种用法的另外一种常见场景是关联同一个开发者账号下的第二个小程序。
由于一个 LeanCloud 应用默认关联一个微信小程序(对应的平台名称是 lc_weapp
),使用小程序系列 API 的时候也都是默认关联到 authData.lc_weapp
字段上。若是想要接入第二个小程序,则须要自行获取到 unionid 与 openid,而后将其做为一个新的第三方平台登陆。这里一样须要用到 AV.User.loginWithAuthDataAndUnionId
方法,但与关联内置的小程序平台(lc_weapp
)有一些不一样:
platform
openid
保存为 uid
(内置的微信平台作了特殊处理能够直接用 openid
而这里是做为通用第三方 OAuth 平台保存所以须要使用标准的 uid
字段)。这里咱们以新的平台 weapp2
为例:
const unionid = ''; const openid = ''; const authData = { uid: openid, session_key: '' }; const platform = 'weapp2'; AV.User.loginWithAuthDataAndUnionId(authData, platform, unionid, { asMainAccount: true }).then(console.log, console.error);
若是一个用户已经登陆,如今经过某种方式获取到了其 unionid(一个常见的使用场景是用户完成了支付操做后在服务端经过 getPaidUnionId 获得了 unionid)但愿与之关联,能够在小程序中使用 AV.User#associateWithWeappWithUnionId()
:
const user = AV.User.current(); // 获取当前登陆用户 user.associateWithWeappWithUnionId(unionid, { asMainAccount: true }).then(console.log, console.error);
上述的登陆 API 对接的是小程序的用户系统,因此使用这些 API 建立的用户没法直接在小程序以外的平台上登陆。若是须要使用 LeanCloud 用户系统提供的其余登陆方式,如用手机号验证码登陆、邮箱密码登陆等,在小程序登陆后设置对应的用户属性便可:
// 小程序登陆 AV.User.loginWithWeapp().then(user => { // 设置并保存手机号 user.setMobilePhoneNumber('13000000000'); return user.save(); }).then(user => { // 发送验证短信 return AV.User.requestMobilePhoneVerify(user.getMobilePhoneNumber()); }).then({ // 用户填写收到短信验证码后再调用 AV.User.verifyMobilePhone(code) 完成手机号的绑定 // 成功后用户的 mobilePhoneVerified 字段会被置为 true // 此后用户即可以使用手机号加动态验证码登陆了 }).catch(console.error);
验证手机号码功能要求在 控制台 > 存储 > 设置 > 用户帐号 启用「用户注册时,向注册手机号码发送验证短信」。
若是你的应用已经在使用 LeanCloud 的用户系统,或者用户已经经过其余方式注册了你的应用(好比在 Web 端经过用户名密码注册),能够经过在小程序中调用 AV.User#associateWithWeapp()
来关联已有的帐户:
// 首先,使用用户名与密码登陆一个已经存在的用户 AV.User.logIn('username', 'password').then(user => { // 将当前的微信用户与当前登陆用户关联 return user.associateWithWeapp(); }).catch(console.error);
更多内容欢迎查看《在微信小程序与小游戏中使用 LeanCloud》。