收藏
回答

wx.getUserProfile不能和wx.login一起使用?

mac 模拟器1.05.2102010 基础库2.16.0

调用wx.login获取code后,再调用wx.getUserProfile,可能会失败,触发fail函数,error msg: ''getUserProfile:fail can only be invoked by user TAP gesture"。

如果不能同时使用,那如何校验用户信息的准确性或者解密encryptedData呢?

最后一次编辑于  2021-04-08
回答关注问题邀请回答
收藏

20 个回答

  • 冫.bindy
    冫.bindy
    2021-04-16

    用了promise.all(),平级调用

    2021-04-16
    有用 8
    回复 17
    • 李百兴
      李百兴
      2021-04-16
      是的,一起触发就可以的
      2021-04-16
      回复
    • tiger
      tiger
      2021-04-22回复李百兴
      自定义token过期了,需要自动登录,怎么重新获取encryptedData和iv呢?
      2021-04-22
      1
      回复
    • 李百兴
      李百兴
      2021-04-22回复tiger
      所以要wx.login,确保code是最新的就可以了
      2021-04-22
      回复
    • lemon
      lemon
      2021-04-25回复李百兴
      有没有代码贴出来参考下
      2021-04-25
      1
      回复
    • 烤鸭zhx
      烤鸭zhx
      2021-04-26
      请问是怎么写的呀,为什么总是报错签名验证失败
      2021-04-26
      回复
    查看更多(12)
  • 苏震巍
    苏震巍
    2021-05-03

    error msg: ''getUserProfile:fail can only be invoked by user TAP gesture"

    这个问题根本不是 wx.login 和 wx.getUserProfile 的调用顺序问题,而是 wx.getUserProfile 不允许自动触发,必须通过用户点击触发(如何使用冒泡等让用户点击是另外一回事)。所以如果 wx.login 是在页面载入时候自动触发的,这时候就不能用 wx.getUserProfile,再加上现在新上线的小程序对于授权提示已经要求比较严了。

    这篇文章供参考:https://www.cnblogs.com/szw/p/14632314.html

    2021-05-03
    有用 9
    回复 6
    • 韩文博
      韩文博
      2021-05-10
      正解  楼主starry 说的同时执行是错误的  开发过的都知道 他估计是没开发就回答了
      2021-05-10
      回复
    • Blue
      Blue
      2021-08-30回复韩文博
      楼主说的没错啊,点击事件触发再执行promise.all不就好了?
      2021-08-30
      回复
    • Blue
      Blue
      2021-08-30
      https://blog.csdn.net/weixin_42289080/article/details/120001198
      2021-08-30
      回复
    • Blue
      Blue
      2021-08-30回复韩文博
      https://blog.csdn.net/weixin_42289080/article/details/120001198
      2021-08-30
      回复
    • 农民工二代1991
      农民工二代1991
      2021-09-14
      我把app.js的onLaunch里的 wx.login({
            success: res => {
              // 发送 res.code 到后台换取 openId, sessionKey, unionId
            }
          })
      删了呢,就不会出发wx.login了,官方给的示例代码是有问题的吗,为啥都不用啊
      wx.login({
        success (res) {
          if (res.code) {
            //发起网络请求
            wx.request({
              url: 'https://example.com/onLogin',
              data: {
                code: res.code
              }
            })
          } else {
            console.log('登录失败!' + res.errMsg)
          }
        }
      })
      2021-09-14
      1
      回复
    查看更多(1)
  • 耿霄
    耿霄
    2021-04-08

    wx.getUserProfile 用户才能触发,wx.login 不需要用户触发

    如果让我们重新设计用户登陆模块,会怎么设计呢?

    如果是我的话,我会这样设计:

    1.用 wx.login 获取 openId(unionId),这个过程是静默的,不需要用户参与,这个能满足市场大多数应用的需求

    2.对于社交分享类的应用,可以进入首页后,用户点击首页可点击区域时,申请用户头像信息(申请成功后保存到后端)

    3.在我的页面在增加个用户头像更新能力即可

    4.对于分享无法获取实时头像的问题,可以在用户点击分享时,先申请获取用户最新头像,然后在进行分享

    这段时间社区很多人吐槽,其实我们还是要看这些改到背后的事情1.对用户隐私要求越来越严,权限细分越来越细,我觉得是好事

    2.我们要抛出历史包袱去想用户授权,别被历史包袱所束缚

    3.getUserInfo 的能力可以通过 wx.login 和 wx.getUserProfile 来实现,都是只需要用户操作一次,唯一的弊端是 wx.getUserProfile  每次都需要用户触发才能拿到最新头像

    4.我觉得没有几个应用对头像的更新频次比微信本身要高,所以也不用在纠结了头像是否为最新的了,只需要提供用户具有更新头像的能力即可

    2021-04-08
    有用 3
    回复 7
    • 李百兴
      李百兴
      2021-04-08
      getUserProfile拿到的加密数据,需要把wx.login拿到的code传给后端,后端才能解密。为什么不直接用明文数据,因为不安全
      2021-04-08
      1
      回复
    • 若水
      若水
      2021-04-15回复李百兴
      你好,我这边session失效时,原先是通过调用重新获取加密数据,然后传到后台登录的,现在getUserProfile必须通过点击才能获取信息,所以session失效时,无法重新登录,请问这个你是怎么解决的
      2021-04-15
      回复
    • 李百兴
      李百兴
      2021-04-15回复若水
      利用事件冒泡,父子元素的点击事件分别触发login和getUserProfile,把结果分别放到data上,再watch这两个值,都不为空的情况下,请求接口,把加密信息和code传给后端
      2021-04-15
      2
      回复
    • 噜啦噜啦嘞
      噜啦噜啦嘞
      2021-04-16
      getUserProfile在2.10.4-2.15.0之间的版本还在灰度,获取不到加密信息,getUserInfo返回的也是匿名的信息,这个怎么解决呢?
      2021-04-16
      1
      回复
    • 李百兴
      李百兴
      2021-04-19回复噜啦噜啦嘞
      开发版和体验版拿不到加密信息,正式版是没有问题的
      2021-04-19
      回复
    查看更多(2)
  • Shivane
    Shivane
    2021-08-24

    1.网上的promise.all的方式处理,我没试但是我感觉是不行的。all只是把login和getinfo同时运行罢了,但是这两个实际都是异步,到底哪个先触发实际是没法确定的。

    2.我这里搞了个比较巧妙的方式,是Taro当然微信原生的代码也是一样的处理方式,原理相同。

      getInfo= async()=>{

        var res = await Taro.getUserProfile({desc:this.login()})

        console.log(res);

      }

      login = ()=>{

        Taro.login().then((res)=>{console.log(res);})

        return '用于完善会员资料';

      }

    这样login一定比getUserProfile先执行,后面同时拿到两个接口的结果,丢给服务器就行。这个解密失败的问题,一定要保证login的网络请求先getUserProfile到达,然后微信服务器才会更新数据。


    2021-08-24
    有用 1
    回复 3
    • D
      D
      2021-09-26
      6啊。可惜手机号授权没有desc参数可以利用,不知道自己加个参数行不行
      2021-09-26
      回复
    • 亚子
      亚子
      2021-09-27
      牛啊牛啊,这才是正解
      2021-09-27
      回复
    • 爱希德鲁
      爱希德鲁
      2021-11-23
      这样跟直接按顺序执行login和getUserProfile没区别
      2021-11-23
      回复
  • v
    v
    2021-06-09

    promise.all同级调用并不能完美解决顺序问题。

    用promise串行,完整代码实现:https://viencoding.com/article/300

    代码片段:

    wxLogin:function (e) {
          // 注意,一定要用这种把函数定义成变量的方式,不要直接用,否则就会出现[getUserProfile:fail can only be invoked by user TAP gesture]的错误
        let p1 = wxSilentLogin()
        let p2 = wxGetUserProfile()
        p1.then(code => {
          return code
        }).then(code => {
          return new Promise((resolve, reject) => {
            p2.then(res => {
              resolve({code, iv: res.iv, encryptedData: res.encryptedData})
            }).catch(err => {
              reject(err)
            })
          })
        }).then(res => {
                // 请求服务器
          wx.request({
            url: 'https://viencoding.com/api/v1/wx/login',
            method: 'post',
            data: {
              code: res.code,
              encrypted_data:  res.encryptedData,
              iv: res.iv
            },
            header: {
              'content-type': 'application/json' // 默认值
            },
            success (res) {
              console.log(res.data) // 这里是登陆成功服务器返回值
            }
          })
        }).catch((err) => {
          console.log(err)
        })
    }
    
    2021-06-09
    有用 1
    回复 4
  • 燕玖
    燕玖
    2021-06-02

    我使用 uniapp 开发的,但可以借鉴下。初学者,如有错误请见谅!

    用wx.login获取code后在回调里发起一个弹窗用于触发wx.getUserProfile

    代码如下:

    wx.login({
      success(res) {
        if (res.code) {
          const code = rs.code;
          uni.request({//获取openID
            url: 'https://jiudaotian.cn', //仅为示例,并非真实接口地址。
            data: {code: code},
            success: (rs) => {//返回状态来判断是否授权过了
              uni.showModal({
                title: '提示',
                content: '检查到您是首次使用小程序,我们希望获得您的个人信息,以便为您提供更好的服务!',
                showCancel: false,
                success: function(res) {
                  if (res.confirm) {
                    wx.getUserProfile({
                      desc: '用于完善用户资料', 
                      success: (res) => {
                      }
                    });
                  }
                }
              });
          }
        });
        }
      }
    });
    


    2021-06-02
    有用 1
    回复 6
    • .._
      .._
      2021-06-02回复k
      并不会,这里用户已经做了手动触发
      2021-06-02
      回复
    • .._
      .._
      2021-06-02
      完美解决
      2021-06-02
      回复
    • k
      k
      2021-06-02回复.._
      嗯嗯 没问题,但是会有两个弹窗。还有就是如果需要用wx.login的code和wx.getUserProfile获取的加密信息,然后解密,这样写有些不妥。code有效期是5分钟。如果五分钟没有点击按钮。就会有问题啦。
      2021-06-02
      回复
    • 叶耳朵🥹
      叶耳朵🥹
      2021-06-17
      调用手机号也可以这么整。
      2021-06-17
      回复
    • Ⅱ
      2021-09-08
      源码能发一下吗
      2021-09-08
      回复
    查看更多(1)
  • Josie🥽
    Josie🥽
    2021-05-13

    可以先调用getUserProfile再调用wx.login

    2021-05-13
    有用 1
    回复 5
    • 天际小鱼干
      天际小鱼干
      2021-06-19
      不能这么做,这样会偶发性解密失败
      2021-06-19
      回复
    • 管宇星
      管宇星
      2021-07-14回复天际小鱼干
      哪里可以看到相关的错误原因么?的确发生了偶发性的解密失败
      2021-07-14
      回复
    • D
      D
      2021-07-16
      wx.getUserProfile 不能在 wx.login之前,否则就会偶发失败。
      但是放在wx.login之后,又弹不出授权窗口,真的是两难。
      2021-07-16
      2
      回复
    • 黄昏
      黄昏
      2021-08-26回复D
      接口有毒吧,返回解密信息的时候直接返回code 多省事 飞到tm拆成两个接口  插件里面都是直接返回 又不是实现不来
      2021-08-26
      回复
    • v
      v
      2021-09-14
      promise串行调用可解决 https://viencoding.com/article/300
      2021-09-14
      回复
  • Blue
    Blue
    2021-08-30

    https://blog.csdn.net/weixin_42289080/article/details/120001198 使用实例,欢迎参考,希望帮到你

    2021-08-30
    有用
    回复
  • 稳当的
    稳当的
    2021-08-12

    不要把这些方法放在setTimeout里调用,比如包裹防抖函数等

    2021-08-12
    有用
    回复
  • 掌柜
    掌柜
    2021-08-11

    我的解决思路:

    用户点击登录后,调用函数bindtap="getUserProfile"。

    getUserProfile: function(e){

    wx.login() //获取code

    wx.getUserProfile( //获取授权信息

    //success成功后执行以下操作:

    //先弹出一个wx.showToast,延迟时间duration为2秒,目的让用户看到程序正在执行,提高用户体验

    //设置一个定时3秒后执行submitLogin()函数:setTimeout(submitLogin(), 3000),目的是使得wx.login()执行完毕生成code

    )

    },

    submitLogin(){ // 赋值code + 授权信息,然后提交

    wx.request() 提交api

    }

    2021-08-11
    有用
    回复

正在加载...

登录 后发表内容
问题标签