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

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

一、

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

这是服务端的

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

 注意:

参数一:获取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>

猜你喜欢

转载自blog.csdn.net/weixin_48594833/article/details/128685560