微信小程序 - 实现手机号登录--授权并获取手机号保存至本地

news2024/11/18 13:45:21

详细代码请见文档最下方,仅供参考,更多需要请查看官方文档

一、

微信官方文档 | 获取手机号

这是服务端的

 这是我们前端获取手机号需要给接口传递的两个参数

 

 注意:

参数一:获取access_token需要用到小程序密钥,这个需要从服务端获取,也就是需要请求后端接口获取access_token,千万不要将小程序密钥写在前端代码中,必须要从服务端获取。

参数二:code的获取我们可以点击后面的 "手机号获取凭证" 查看用法,很简单。下面 二、 就是手机号获取凭证地址。

二、

 微信官方文档 | 手机号获取凭证

注意:这里有基础库版本限制,所以我们最好做一下低版本兼容处理;

 

个人使用时碰到的坑:

微信开放社区 | 使用getPhoneNumber获取手机号code,微信PC拿不到code,手机端可以获取到? 

详细实现代码:

<template>
  <view class="flex">
    <view class="title">
      <view class="logo">
        <image src="/static/image/logo.png" mode="widthFix" />
      </view>
    </view>
    <!-- 手机号登录  --授权并获取手机号保存至本地 -->
    <button
      type="default"
      class="loginButton"
      open-type="getPhoneNumber"
      @getphonenumber="getPhoneNumber"
    >
      <view class="row">
        <view class="icon">
          <u-icon name="weixin-fill" size="28"></u-icon>
        </view>
        <view style="font-size: 30rpx">微信登录</view>
      </view>
    </button>
    <!-- 协议选择 -->
    <view class="serve-rule">
      <u-checkbox-group size="24" @click="changeCheckStatus">
        <u-checkbox
          class="checkbox"
          v-model="checkStatus"
          activeColor="#ff414e"
        ></u-checkbox>
      </u-checkbox-group>
      <view class="protocol-prompt">
        <text @click="changeCheckStatus">本人理解并同意</text>
        <text class="serve-label" @click.stop="onServiceAgreement"
          >《隐私政策》</text
        >
        <text class="serve-label" @click.stop="onUserAgreement"
          >《用户协议》</text
        >
      </view>
    </view>
    <u-toast ref="uToast" />
  </view>
</template>

<script>
export default {
  name: "login",
  data() {
    return {
      phoneCode: "", // 获取手机号使用的code
      phoneNumber: "", // 手机号
      access_token: "", // 用户token

      code: "", // authCode用户code码  ---- 登陆使用的code
      userInfo: "", //用户信息
      id: "",
      checkStatus: false, //协议是否勾选
    };
  },
  onLoad(options) {
    const version = wx.getSystemInfoSync().SDKVersion;
    console.log("当前版本号version", version);
    if (this.compareVersion(version, "2.21.2") >= 0) {
      uni.removeStorageSync("storage_USERPHONE");
      this.getWxCode(); // 获取微信用户code码--登录使用
      this.getAccessToken(); // 获取 accessToken --获取手机号使用
    } else {
      // 如果希望用户在最新版本的客户端上体验您的小程序,可以这样子提示
      wx.showModal({
        title: "提示",
        content:
          "当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。",
      });
    }
  },
  methods: {
    // 获取微信用户code码--登录使用
    async getWxCode() {
      const result = await wx.login();
      // console.log(result);
      if (result.code) {
        this.code = result.code;
        console.log("登录使用的code =====>>>>>>", this.code);
      }
    },
    // 获取 accessToken 注意:要从服务端获取,密钥不能写在前端。 --获取手机号使用
    getAccessToken() {
      this.$http.getAccessToken().then((res) => {
        if (res.success) {
          let resObj = res.datas && res.datas.obj;
          console.log("resObj======>>>>>>", resObj);
          this.access_token = resObj.access_token;
          console.log("that.access_token======>>>>>>", this.access_token);
        }
      });
    },
    // 低版本兼容处理方法封装
    compareVersion(v1, v2) {
      v1 = v1.split(".");
      v2 = v2.split(".");
      const len = Math.max(v1.length, v2.length);

      while (v1.length < len) {
        v1.push("0");
      }
      while (v2.length < len) {
        v2.push("0");
      }

      for (let i = 0; i < len; i++) {
        const num1 = parseInt(v1[i]);
        const num2 = parseInt(v2[i]);

        if (num1 > num2) {
          return 1;
        } else if (num1 < num2) {
          return -1;
        }
      }
      return 0;
    },
    // 获取用户手机号-接口
    getUserPhone() {
      this.$http
        .getPhone({
          code: this.phoneCode,
          access_token: this.access_token,
        })
        .then((res) => {
          // console.log("用户手机号res====>",res)
          if (res.success) {
            let resDatas = res.datas;
            let phoneInfo = JSON.parse(resDatas.phone_info);
            // console.log("获取到的用户手机号相关信息=====>>>>>>", phoneInfo)
            this.phoneNumber = phoneInfo.phoneNumber;
            console.log("获取到的用户手机号=====>>>>>>", this.phoneNumber);
            uni.setStorageSync("storage_USERPHONE", this.phoneNumber);
            this.login();
          }
        });
    },
    // 获取手机号的code并授权
    getPhoneNumber(e) {
      console.log("e=====>>>>>>", e);
      if (this.checkStatus) {
        let detail = e.detail;
        if (detail.errMsg === "getPhoneNumber:ok") {
          let that = this;
          this.phoneCode = detail.code;
          console.log("获取手机号使用的code =====>>>>>>", this.phoneCode);
          if (this.phoneCode) {
            this.getUserPhone();
          } else {
            this.login();
          }
        } else {
          console.log("取消授权!");
        }
      } else {
        uni.showToast({
          icon: "none",
          title: "请阅读并确认隐私政策和用户协议",
        });
      }
    },
    // 登录
    async login() {
      uni.showLoading({
        title: "登录中.....",
        mask: true,
      });
      const res = await this.$http.wxLogin({
        code: this.code,
        udid: "**************",
        appletType: 4,
      });
      if (res.success) {
        if (res.datas.token) {
          uni.setStorageSync("ticket", res.datas.token);
        }
        if (res.datas.obj) {
          uni.setStorageSync("userInfo", res.datas.obj);
          this.id = res.datas.obj.extInfo.id;
        }
        this.getAppletVersion();
        return;
      }
    },
    getAppletVersion() {
      uni.hideLoading();
      uni.reLaunch({
        url: `/pages/index/index`,
      });
    },
    // 切换是否选中复选框
    changeCheckStatus() {
      this.checkStatus = !this.checkStatus;
    },
    // 进入《隐私政策》
    onServiceAgreement() {
      uni.navigateTo({
        url: "/pages/privacy-policy/privacy-policy",
        fail(e) {
          console.log(e);
        },
      });
    },
    // 《用户协议》
    onUserAgreement() {
      uni.navigateTo({
        url: "/pages/user-service-agreement/user-service-agreement",
        fail(e) {
          console.log(e);
        },
      });
    },
  },
};
</script>

<style lang="scss" scoped>
.flex {
  display: flex;
  flex-flow: column nowrap;
  justify-content: flex-start;
  align-items: center;
  position: fixed;
  width: 100vw;
  height: 100vh;
  top: 200rpx;
  left: 0;
  padding: 0 64rpx;

  .title {
    display: flex;
    flex-direction: column;
    align-items: center;
    margin-bottom: 200rpx;
    width: 240rpx;

    .logo {
      width: 360rpx;
      height: 360rpx;
      overflow: hidden;

      image {
        width: 100%;
        height: auto;
      }

      text {
        display: inline-block;
        color: #404040;
      }
    }
  }

  .loginButton {
    width: 100%;
    height: 72rpx;
    background: linear-gradient(142deg, #ff8677 11%, #ff424e 94%);
    border-radius: 88rpx;
    font-size: 32rpx;
    font-family: PingFangSC, PingFangSC-Medium;
    font-weight: 500;
    text-align: center;
    line-height: 52rpx;
    color: #ffffff;
    letter-spacing: 2rpx;
    margin-bottom: 52rpx;
  }

  .serve-rule {
    width: 100%;
    margin-left: 16rpx;
    display: flex;
    align-items: center;
    position: relative;

    .serve-label {
      color: #ff414e;
      // transform: translateX(-10%);
    }
    .protocol-prompt {
      display: inline-block;
      position: absolute;
      left: 34rpx;
    }
  }

  .checkbox {
    margin-right: 0;
  }

  .row {
    padding: 10rpx;
    flex-flow: row nowrap;
    display: flex;
    justify-content: center;
    align-items: center;

    .icon-text {
      color: #007aff;
    }
  }

  .ding-row {
    flex-flow: row nowrap;
    display: flex;
    justify-content: center;
    align-items: center;

    .icon-text {
      color: #007aff;
    }
  }

  .icon {
    margin-right: 10rpx;
    display: flex;
    align-items: center;
  }

  .btn {
    width: 90%;
    overflow: hidden;
    text-align: center;
  }
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/163783.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

你可能不知道的20个Git命令,但真的很实用

如果您曾经浏览过git 手册&#xff08;或 run man git&#xff09;&#xff0c;那么您会注意到 git 的功能比我们大多数人每天使用的要多得多。很多这些命令都非常强大&#xff0c;可以让你的生活更轻松&#xff08;其他命令有点小众&#xff0c;但仍然很高兴知道&#xff09;。…

QT-QStackedWidget多窗口应用

前言&#xff1a; 多窗口应用&#xff0c;例如某微信&#xff0c;页面由1&#xff0c;2&#xff0c;3个布局组成。 1-基本流程 页面1控制页面2&#xff0c;通过选择页面1上的按钮或控件 页面2控制页面3&#xff0c;通过选择页面2上的按钮或控件 2-其中页面2中的页面很…

100、【树与二叉树】leetcode ——105. 从前序与中序遍历序列构造二叉树+106. 从中序与后序遍历序列构造二叉树(C++版本)

106. 从中序与后序遍历序列构造二叉树 题目描述 原题链接&#xff1a;106. 从中序与后序遍历序列构造二叉树 解题思路 中序的特点&#xff1a;左中右&#xff0c;后序的特点&#xff1a;左右中。因此可通过后序序列找到中间结点&#xff0c;然后再根据中间结点&#xff0c;分…

3、关键词与标识符

目录 一、关键词 二、标识符 一、关键词 C语言中有32个关键字&#xff1a; 注意&#xff1a;在C语言中&#xff0c;关键字是不允许作为标识符出现在程序中的。 二、标识符 C语言标识符的命名规则&#xff1a; &#xff08;1&#xff09;所有标识符必须由字母或下画线开头…

KMP算法 看这一篇就够了 图解刨析+代码

目录 问题背景 逐步剖析 KMP如何优化暴力做法 思考 公共前后缀 next数组 如何构建next数组: 代码实现 问题背景 给定一个字符串 S&#xff0c;以及一个模式串P&#xff0c; P 在字符串 S 中多次作为子串出现。 求出模式串 P 在字符串 S 中所有出现的位置的起始下标。 …

说话人识别中的Temporal pooling(时序池化)

概述 Temporal pooling&#xff08;时序池化&#xff09;是说话人识别神经网络中&#xff0c;声学特征经过frame-level变换之后&#xff0c;紧接着会进入的一个layer。目的是将维度为(bs,F,T)(bs,F,T)(bs,F,T)的特征图&#xff0c;变换成维度为(bs,F)(bs,F)(bs,F)的特征向量 …

再不来看看常用的PyCharm快捷键就out了,玩转PyCharm仅此一篇!

最近在学习Python的数据可视化项目&#xff0c;在大学有学过Python&#xff0c;还有一些基础的。目前虽说已经工作&#xff0c;但是兴趣使然&#xff0c;依然想在空闲时间学一些其他技能来充实自己&#xff0c;未雨绸缪&#xff01; 在使用工具的时候&#xff0c;必定会对工具有…

【话题:工作生活】2021年工作总结--这些人,那些事。

Hello Everyone&#xff0c; 我又开始撰写自己的工作总结了。2021年的工作总结&#xff0c;拖得太久&#xff0c;拖得我也不想写了。每次写自己一年的工作总结&#xff0c;总是要耗费我大量的时间与心力&#xff0c;有时&#xff0c;我也真的是心好累。 好了&#xff0c;懒散、…

【人工智能原理自学】隐藏层:神经网络为什么Working

&#x1f60a;你好&#xff0c;我是小航&#xff0c;一个正在变秃、变强的文艺倾年。 &#x1f514;笔记来自B站UP主Ele实验室的《小白也能听懂的人工智能原理》。 &#x1f514;本文讲解隐藏层&#xff1a;神经网络为什么Working&#xff0c;一起卷起来叭&#xff01; 目录一、…

深度学习 11 梯度下降算法改进

数据初始化要点: 1. 梯度下降算法的三种方式: 批量梯度下降法(batch)&#xff0c;即同时处理整个训练集.小批量梯度下降法&#xff08;Mini-Batch &#xff09;每次同时处理固定大小的数据集.随机梯度下降法&#xff08;stochastic gradient descent&#xff09;, 每次随机选…

acwing基础课——约数

由数据范围反推算法复杂度以及算法内容 - AcWing 常用代码模板4——数学知识 - AcWing 基本思想&#xff1a; 首先&#xff0c;约数&#xff0c;又称因数。整数a除以整数b(b≠0)除得的商正好是整数而没有余数&#xff0c;我们就说a能被b整除&#xff0c;或b能整除a。a称为b的…

怎样才能过好这一生?

文章目录1. 日拱一卒&#xff0c;功不唐捐1.1 适当的时候给自己一个奖励1.2 一个人可能走的更快&#xff0c;但一群人才能走的更远1.3 通过一些事情去逼自己一把1.4 从真理中去感悟1.5 当你面临绝路时2. 梦想的意义不在于实现3. 孤独4. 烦恼5. 别总说来日方长6. 忍和韧性7. 事情…

【linux kernel】linux内核重要函数 | do_initcalls

文章目录一、导读二、do_initcalls三、构造section并添加函数&#xff08;3-1&#xff09;构造初始化调用section&#xff08;3-2&#xff09;向section中添加函数四、总结一、导读 在linux内核启动过程中&#xff0c;会向终端打印出很多的日志信息&#xff0c;从这些日志信息…

c++开源协程库libgo介绍及使用

协程这个概念&#xff0c;最近这几年可是相当地流行了。尤其 go 语言问世之后&#xff0c;内置的协程特性&#xff0c;完全屏蔽了操作系统线程的复杂细节。甚至使 go 开发者“只知有协程&#xff0c;不知有线程”了。当然 C也有高性能的协程库&#xff0c;比如我了解到的微信的…

基于微信小程序的企业职工薪资查询系统小程序

文末联系获取源码 开发语言&#xff1a;Java 框架&#xff1a;ssm JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7/8.0 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.3.9 浏览器…

卷积神经网络(CNN)详细介绍及其原理详解

文章目录前言一、什么是卷积神经网络二、输入层三、卷积层四、池化层五、全连接层六、输出层七、回顾整个过程总结前言 本文总结了关于卷积神经网络&#xff08;CNN&#xff09;的一些基础的概念&#xff0c;并且对于其中的细节进行了详细的原理讲解&#xff0c;通过此文可以十…

自动(智能)驾驶 | 4D雷达的数据集

上篇文章分享了关于Oculii 4D雷达的两篇报告。数据集是一个非常重要的研究工具&#xff0c;对于4D雷达领域来说&#xff0c;处于一个研究前沿的位置&#xff0c;鲜有公开的数据集&#xff0c;目前能找到的数据集有&#xff1a; 这些文章中的数据集有不少博主也写过&#xff0c…

S1000D规范导读

S1000D最初是由欧洲航空工业联盟开发的技术出版物规范&#xff0c;它主要为具有较长生命的复杂产品运行和维修而设计。这些年不断发展&#xff0c;已经扩展到这些行业的产品&#xff1a;国防系统 - 包括海、陆、空的产品&#xff0c;民用航空产品&#xff0c;基建行业产品和船舶…

15/365 java static final

1.static属性,方法 类内属性或方法用static修饰&#xff0c;表示该属性或方法属于类&#xff0c;不依赖于实例对象&#xff0c;所以不需要用对象调用&#xff0c;而是直接用类名调用。 static方法只能调用其他static方法&#xff0c;而普通方法可以调用其他的普通方法和stati…

Vue3商店后台管理系统设计文稿篇(二)

记录使用vscode构建Vue3商店后台管理系统&#xff0c;这是第二篇&#xff0c;主要记录Vue3中生命周期钩子&#xff0c;模板语法&#xff0c;以及相关的代码 文章目录一、Vue3生命周期二、Vue3模板语法三、代码展示正文内容&#xff1a; 一、Vue3生命周期 每个 Vue 实例在被创建…