微信小程序授权手机号

箴水技术分享 . 发布于 2023-05-29 10:18:00 . 阅读 2861

官方文档

获取手机号 | 微信开放文档 (客户端)

后端 API | 微信开放文档(服务端)

指南丨微信开放文档

接口入参

目前该接口针对非个人开发者,且完成了认证的小程序开放(不包含海外主体)。需谨慎使用,若用户举报较多或被发现在不必要场景下使用,微信有权永久回收该小程序的该接口权限;

在使用该接口时,用户可使用微信绑定手机号进行授权,也添加非微信绑定手机号进行授权。若开发者仅通过手机号作为业务关联凭证,在重点场景可适当增加短信验证逻辑。

代码示例

<button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber"></button>

Page({
getPhoneNumber (e) {
console.log(e.detail.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>