草庐IT

微信小程序之登录

Suifqwu 2023-04-04 原文

目录

1、登录流程时序

1.1、wx.login(Object object)

1.1.1、功能描述

1.1.2、参数

1.1.3、object.success 回调函数

1.2、auth.code2Session

1.2.1、请求地址

1.2.2、请求参数

1.2.3、返回值

2、使用微信登录

 2.1、小程序端js文件

2.2、云函数端js文件

3、获取手机号码

3.1、小程序端代码

3.2、云函数端js文件


        小程序可以通过微信官方提供的登录能力方便地获取微信提供的用户身份标识,快速建立小程序内的用户体系。详情查看:微信官方文档-小程序登录

1、登录流程时序

说明

  1. 调用 wx.login() 获取 临时登录凭证code ,并回传到开发者服务器。
  2. 调用 auth.code2Session 接口,换取 用户唯一标识 OpenID 、 用户在微信开放平台帐号下的唯一标识UnionID(若当前小程序已绑定到微信开放平台帐号) 和 会话密钥 session_key

之后开发者服务器可以根据用户标识来生成自定义登录态,用于后续业务逻辑中前后端交互时识别用户身份

注意事项

  1. 会话密钥 session_key 是对用户数据进行 加密签名 的密钥。为了应用自身的数据安全,开发者服务器不应该把会话密钥下发到小程序,也不应该对外提供这个密钥
  2. 临时登录凭证 code 只能使用一次

1.1、wx.login(Object object)

1.1.1、功能描述

        调用接口获取登录凭证(code)。通过凭证进而换取用户登录态信息,包括用户在当前小程序的唯一标识(openid)、微信开放平台帐号下的唯一标识(unionid,若当前小程序已绑定到微信开放平台帐号)及本次登录的会话密钥(session_key)等。用户数据的加解密通讯需要依赖会话密钥完成

1.1.2、参数

属性类型默认值必填说明
timeoutnumber超时时间,单位ms
successfunction接口调用成功的回调函数
failfunction接口调用失败的回调函数
completefunction接口调用结束的回调函数(调用成功、失败都会执行)

1.1.3、object.success 回调函数

属性类型说明
codestring用户登录凭证(有效期五分钟)。开发者需要在开发者服务器后台调用 auth.code2Session,使用 code 换取 openid、unionid、session_key 等信息

1.2、auth.code2Session

        注意:这个作用于服务端,不要在客户端调用

        登录凭证校验。通过 wx.login 接口获得临时登录凭证 code 后传到开发者服务器调用此接口完成登录流程

1.2.1、请求地址

GET https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code

1.2.2、请求参数

属性类型默认值必填说明
appidstring小程序 appId
secretstring小程序 appSecret
js_codestring登录时获取的 code
grant_typestring授权类型,此处只需填写 authorization_code

1.2.3、返回值

属性类型说明
openidstring用户唯一标识
session_keystring会话密钥
unionidstring用户在开放平台的唯一标识符,若当前小程序已绑定到微信开放平台帐号下会返回,详见 UnionID 机制说明
errcodenumber错误码
errmsgstring错误信息

errcode 的合法值

说明
-1系统繁忙,此时请开发者稍候再试
0请求成功
40029code 无效
45011频率限制,每个用户每分钟100次
40226高风险等级用户,小程序登录拦截 。风险等级详见用户安全解方案

        我真的是晕倒了,如果你使用的是云开发自带的数据库来存储的话,其实你是不需要获取openid的行为的,但是我一开始不知道呀,弄着弄着发现其实这个是有的,所以就分了两个了,一个是获取微信头像、昵称和openid的,一个是使用自带的获取手机号码的

2、使用微信登录

工作步骤:

  1. wx.getUserProfile弹窗框体显示用户的头像和昵称
  2. 确定后wx.login获取code
  3. 发送命令到服务器获取openid以及账户信息

 2.1、小程序端js文件

async getUserProfile(e) {
    wx.getUserProfile({
      desc: '用于获取用户个人信息',
      success: function (detail) {
        
        wx.login({
          success: res => {
            var code = res.code; //登录凭证
            wx.cloud.callFunction({
              name: "getCurrentUserInfo",
              data: {
                encryptedData: detail.encryptedData,
                iv: detail.iv,
                code: code,
                userInfo: detail.rawData
              }
            }).then(res => {
              console.log("res: ",res);
              var openid = res.result.openid;
              var status = res.result.status;
              var phone = res.result.phone;
              console.log("openid: ",openid);
              console.log("status: ",status);
              console.log("phone: ",phone);
              console.log("nickName: ",detail.userInfo.nickName);
              
              if(phone==undefined){
                console.log("需要绑定手机号");
              }else{
                console.log("授权成功");
              }
            }).catch(res => {
              console.log("res3: ",res);
            })
          }
        });
      },
      fail: function () {
       wx.showModal({
         content: '取消授权将会影响相关服务,您确定取消授权吗?',
         success (res) {
           if (res.confirm) {
             wx.showToast({
               title: '已取消授权',
               duration: 1500
             })
           } else if (res.cancel) {
             this.getUserProfile()
           }
         }
       })
      }
    })
  }

2.2、云函数端js文件

cloud.init({
  env: cloud.DYNAMIC_CURRENT_ENV
})
const db = cloud.database()
// 云函数入口函数
let user_id;
let user_uid;
exports.main = async (event, context) => {
  const wxContext = cloud.getWXContext()
  let code = event.code;//获取小程序传来的code
  let encryptedData = event.encryptedData;//获取小程序传来的encryptedData
  let iv = event.iv;//获取小程序传来的iv
  let userInfo = JSON.parse(event.userInfo) //获取个人信息
  let appid = "xxxxxxxxx";//自己小程序后台管理的appid,可登录小程序后台查看
  let secret = "xxxxxxxxx";//小程序后台管理的secret,可登录小程序后台查看
  let grant_type = "authorization_code";// 授权(必填)默认值
  let url = "https://api.weixin.qq.com/sns/jscode2session?grant_type="+grant_type+"&appid="+appid+"&secret="+secret+"&js_code="+code;
  const stat = await new Promise((resolve, reject) => {
    request(url, (err, response, body) => {
      if (!err && response.statusCode == 200) {
        let _data = JSON.parse(body)
        let UserCount = 0;
        user_id = _data.openid
        user_uid = _data.unionid
        db.collection('Account').where({
          user_id: _data.openid // 填入当前用户 openid
        }).count().then(res => {
          UserCount = res.total;
          if(UserCount == 0){/* 插入当前列表 */
            db.collection('Account').add({
              data: {
                user_id: _data.openid,
                nickName: userInfo.nickName,
                avatarUrl: userInfo.avatarUrl,
                gender: userInfo.gender,
                phone: ''
              }
            })
            .then(res => {
              resolve("Insert success!");
            })
            .catch(res => {
              reject("Insert fail!");
            })
          }else if(UserCount == 1){/* 更新当前列表 */
            db.collection('Account').where({
              user_id: _data.openid // 填入当前用户 openid
            }).update({
              data: {
                nickName: userInfo.nickName,
                avatarUrl: userInfo.avatarUrl,
                gender: userInfo.gender
              }
            })
            .then(res => {
              resolve("Update success!");
            }).catch(res => {
              reject("Update fail!");
            })
          }else if(UserCount > 1){/* 删除所有此id的并且重新添加 */
            db.collection('Account').where({
              user_id: _data.openid // 填入当前用户 openid
            }).remove()
            .then(res => {
              db.collection('Account').add({
                data: {
                  user_id: _data.openid,
                  nickName: userInfo.nickName,
                  avatarUrl: userInfo.avatarUrl,
                  gender: userInfo.gender,
                  phone: ''
                }
              })
              resolve("Remove and insert success!");
            }).catch(res => {
              reject("Remove fail!");
            })
          }
        })
      }
    })
  })
  const CurrentPhoneObject = await db.collection('Account').where({
    user_id: user_id // 填入当前用户 openid
  }).get()
  const CurrentPhone = CurrentPhoneObject.data[0].phone
  console.log("CurrentPhone: ",CurrentPhone);
  console.log("stat: ",stat);
  console.log("user_id: ",user_id);
  console.log("user_uid: ",user_uid);
  return {
    status: stat,
    CurrentPhone: CurrentPhone,
    openid: user_id,
    unionid: user_uid
  }
}

3、获取手机号码

        因为需要用户主动触发才能发起获取手机号接口,所以该功能不由 API 来调用,需用 button 组件的点击来触发。另外,新版本接口不再需要提前调用wx.login进行登录。

<button type="primary" open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">获取手机号</button>

3.1、小程序端代码

 async getPhoneNumber(res) {
    console.log(res)
    const errMsg = res.detail.errMsg
    if (errMsg != "getPhoneNumber:ok"){
      wx.showToast({
        title: '授权失败',
        icon: 'error'
      })
      return
    }
    const cloudId = res.detail.cloudID
    const cloudIdList = [cloudId]
    wx.showLoading({
      title: '获取中',
      mask: true
    })
    const cloudFunRes = await wx.cloud.callFunction({
      name: "getPhoneNumber",
      data: {
        cloudIdList
      }
    })
    console.log("cloudFunRes: ",cloudFunRes)
    const jsonStr = cloudFunRes.result.dataList[0].json
    const jsonData = JSON.parse(jsonStr)
    const phoneNumber = jsonData.data.phoneNumber
    console.log(phoneNumber)
    this.setData({
      userPhone: phoneNumber
    })
    wx.hideLoading({
      success: (res) => {},
    })
  },

3.2、云函数端js文件

const cloud = require('wx-server-sdk')

cloud.init({
  env: cloud.DYNAMIC_CURRENT_ENV
})

// 云函数入口函数
exports.main = async (event) => {
  const wxContext = cloud.getWXContext()
  const openid = wxContext.OPENID
  const appid = wxContext.APPID
  const unionid = wxContext.UNIONID
  const enc = wxContext.ENV
  const cloudIdList = event.cloudIdList
  try {
    const result = await cloud.openapi.cloudbase.getOpenData({
      openid: openid,
      cloudidList: cloudIdList
    })
    
    const jsonStr = result.dataList[0].json
    const jsonData = JSON.parse(jsonStr)
    const phoneNumber = jsonData.data.phoneNumber
    console.log("phoneNumber: ",phoneNumber)

    return result
  } catch (err) {
    return err
  }
}

主要代码来自博主:https://blog.csdn.net/yancy_peng/article/details/121308428

有关微信小程序之登录的更多相关文章

  1. 微信小程序通过字典表匹配对应数据 - 2

    前言一般来说,前端根据后台返回code码展示对应内容只需要在前台判断code值展示对应的内容即可,但要是匹配的code码比较多或者多个页面用到时,为了便于后期维护,后台就会使用字典表让前端匹配,下面我将在微信小程序中通过wxs的方法实现这个操作。为什么要使用wxs?{{method(a,b)}}可以看到,上述代码是一个调用方法传值的操作,在vue中很常见,多用于数据之间的转换,但由于微信小程序诸多限制的原因,你并不能优雅的这样操作,可能有人会说,为什么不用if判断实现呢?但是if判断的局限性在于如果存在数据量过大时,大量重复性操作和if判断会让你的代码显得异常冗余。wxswxs相当于是一个独立

  2. 计算机毕业设计ssm+vue基本微信小程序的小学生兴趣延时班预约小程序 - 2

    项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU

  3. 微信小程序开发入门与实战(Behaviors使用) - 2

    @作者:SYFStrive @博客首页:HomePage📜:微信小程序📌:个人社区(欢迎大佬们加入)👉:社区链接🔗📌:觉得文章不错可以点点关注👉:专栏连接🔗💃:感谢支持,学累了可以先看小段由小胖给大家带来的街舞👉微信小程序(🔥)目录自定义组件-behaviors    1、什么是behaviors    2、behaviors的工作方式    3、创建behavior    4、导入并使用behavior    5、behavior中所有可用的节点    6、同名字段的覆盖和组合规则总结最后自定义组件-behaviors    1、什么是behaviorsbehaviors是小程序中,用于实现

  4. ruby - 使用 Ruby 和 Mechanize 登录网站 - 2

    我需要从站点抓取数据,但它需要我先登录。我一直在使用hpricot成功地抓取其他网站,但我是使用mechanize的新手,我真的对如何使用它感到困惑。我看到这个例子经常被引用:require'rubygems'require'mechanize'a=Mechanize.newa.get('http://rubyforge.org/')do|page|#Clicktheloginlinklogin_page=a.click(page.link_with(:text=>/LogIn/))#Submittheloginformmy_page=login_page.form_with(:act

  5. Ubuntu20.04系统WineHQ7.0安装微信 - 2

    提供3种Ubuntu系统安装微信的方法,在Ubuntu20.04上验证都ok。1.WineHQ7.0安装微信:ubuntu20.04安装最新版微信--可以支持微信最新版,但是适配的不是特别好;比如WeChartOCR.exe报错。2.原生微信安装:linux系统下的微信安装(ubuntu20.04)--微信适配的最好,反应最快,但是微信版本只到2.1.1,版本太老,很多功能都没有。3.深度deepin-wine6安装微信:ubuntu20.04+系统deepin-wine6安装新版微信--综合比较好,当前个人使用此种方法1个月,微信版本3.4;没什么大问题,尚可。一、WineHQ7.0安装微信

  6. 微信小程序订餐系统 - 2

    对传统的餐饮商家来说,小程序很好地解决了餐厅线下线上连接的问题,在引流获客、节约人力、营销宣传、塑造会员体系、改善消费体验等方面都有很大帮助。小程序点餐可以帮助餐饮企业节省一大把人力开支。一个包含扫码点单、菜品管理、优惠券推送、外卖配送的小程序,商家花几万元就能完成开发测试并投入。商家为什么要开通“扫码点餐”1.解决服务员不够用的问题。2.不怕顾客跑单漏单。3.在微信就能管理菜品、查看营业额。4.订单小票显示顾客桌号和已点菜品。5.可在“附近的小程序”找到您的门店。如今餐饮业常用的三种经营模式:1堂食点单模式客人通过小程序堂食点单。商家可以在微信扫码点餐小程序管理后台根据自己店内情况来设置不同

  7. 最新版人脸识别小程序 图片识别 生成二维码签到 地图上选点进行位置签到 计算签到距离 课程会议活动打卡日常考勤 上课签到打卡考勤口令签到 - 2

    技术选型1,前端小程序原生MINA框架cssJavaScriptWxml2,管理后台云开发Cms内容管理系统web网页3,数据后台小程序云开发云函数云开发数据库(基于MongoDB)云存储4,人脸识别算法基于百度智能云实现人脸识别一,用户端效果图预览老规矩我们先来看效果图,如果效果图符合你的需求,就继续往下看,如果不符合你的需求,可以跳过。1-1,登录注册页可以看到登录页有注册入口,注册页如下我们的注册,需要管理员审核,审核通过后才可以正常登录使用小程序1-2,个人中心页登录成功以后,我们会进入个人中心页我们在个人中心页可以注册人脸,因为我们做人脸识别签到,需要先注册人脸才可以进行人脸比对,进

  8. ruby-on-rails - 使用用户或管理员模型和 Basecamp 样式子域设计登录 - 2

    我为Devise用户和管理员提供了不同的模型。我也在使用Basecamp风格的子域。除了我需要能够以用户或管理员身份进行身份验证的一些Controller和操作外,一切都运行良好。目前我有authenticate_user!在我的application_controller.rb中设置,对于那些只有管理员才能访问的Controller和操作,我使用skip_before_filter跳过它。不幸的是,我不能简单地指定每个Controller的身份验证要求,因为我仍然需要一些Controller和操作才能被用户或管理员访问。我尝试了一些方法都无济于事。看来,如果我移动authentica

  9. ruby - 如何使用 omniauth/oauth 对每秒登录数进行基准测试? ( ruby +rspec) - 2

    我想用一个(自己的)omniauth提供商来衡量每秒可以登录多少次。我需要了解此omniauth/oauth请求的性能如何,以及此身份验证是否具有可扩展性?到目前为止我得到了什么:defperformance_auth(user_count=10)bm=Benchmark.realtimedouser_count.timesdo|n|forkdoclick_on'Logout'omniauth_config_mock(:provider=>"foo",:uid=>n,:email=>"foo#{n}@example.net")visit"/account/auth/foo/"enden

  10. ruby - 如何使用 Ruby 和 eventmachine 登录? - 2

    我正在使用Ruby和Eventmachine库编写一个应用程序。我真的很喜欢非阻塞I/O和事件驱动系统的想法,我遇到的问题是日志记录。我正在使用Ruby的标准记录器库。并不是说日志记录需要永远,但它似乎不应该阻塞,但它确实阻塞了。是否有某个库将Ruby的标准记录器实现扩展为非阻塞的,或者我应该只调用EM::defer进行日志记录调用?有没有办法让eventmachine已经为我做这件事? 最佳答案 我最终将记录器包装在一个启动线程并具有FIFO队列的单例类中。日志记录会将日志信息转储到队列中,线程只是循环,从队列中拉出内容并使用真正

随机推荐