小兔鲜儿 - 微信登录

news2024/11/19 7:26:45

目录

微信登录​

登录方式

静态结构​

获取登录凭证​

获取手机号码​

微信登录接口(生产环境) 

模拟手机登录(开发环境)

用户信息持久化存储​


涉及知识点:微信授权登录,文件上传,Store 状态管理等。

微信登录​

微信小程序的开放能力,允许开发者获取微信用户的基本信息(昵称、性别、手机号码等),开发者常用来实现注册/登录的功能。

登录方式

常见登录/注册方式:

  1. 用户名/手机号 + 密码
  2. 手机号 + 验证码
  3. 授权登录

实际开发过程中常常需要实现以上的一种或多种方式,我们的项目主要实现授权登录

微信授权登录

用户在使用小程序时,其实已登录微信,其本质上就是:微信授权给小程序读取微信用户信息

开放接口 / 登录 / wx.login (qq.com)icon-default.png?t=N7T8https://developers.weixin.qq.com/miniprogram/dev/api/open-api/login/wx.login.html

开放能力 / 用户信息 / 手机号快速验证组件 (qq.com)icon-default.png?t=N7T8https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getPhoneNumber.html

传统登录方式

传统登录方式,一般是通过输入密码或者手机验证码实现登录。

 温馨提示:接口文档中提供练习使用的登录接口,大家可在课后自行完成。

静态结构​

登录页

// src/pages/login/login.vue

<script setup lang="ts">
//
</script>

<template>
  <view class="viewport">
    <view class="logo">
      <image
        src="https://pcapi-xiaotuxian-front-devtest.itheima.net/miniapp/images/logo_icon.png"
      ></image>
    </view>
    <view class="login">
      <!-- 网页端表单登录 -->
      <!-- <input class="input" type="text" placeholder="请输入用户名/手机号码" /> -->
      <!-- <input class="input" type="text" password placeholder="请输入密码" /> -->
      <!-- <button class="button phone">登录</button> -->

      <!-- 小程序端授权登录 -->
      <button class="button phone">
        <text class="icon icon-phone"></text>
        手机号快捷登录
      </button>
      <view class="extra">
        <view class="caption">
          <text>其他登录方式</text>
        </view>
        <view class="options">
          <!-- 通用模拟登录 -->
          <button>
            <text class="icon icon-phone">模拟快捷登录</text>
          </button>
        </view>
      </view>
      <view class="tips">登录/注册即视为你同意《服务条款》和《小兔鲜儿隐私协议》</view>
    </view>
  </view>
</template>

<style lang="scss">
page {
  height: 100%;
}

.viewport {
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: 20rpx 40rpx;
}

.logo {
  flex: 1;
  text-align: center;
  image {
    width: 220rpx;
    height: 220rpx;
    margin-top: 15vh;
  }
}

.login {
  display: flex;
  flex-direction: column;
  height: 60vh;
  padding: 40rpx 20rpx 20rpx;

  .input {
    width: 100%;
    height: 80rpx;
    font-size: 28rpx;
    border-radius: 72rpx;
    border: 1px solid #ddd;
    padding-left: 30rpx;
    margin-bottom: 20rpx;
  }

  .button {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 80rpx;
    font-size: 28rpx;
    border-radius: 72rpx;
    color: #fff;
    .icon {
      font-size: 40rpx;
      margin-right: 6rpx;
    }
  }

  .phone {
    background-color: #28bb9c;
  }

  .wechat {
    background-color: #06c05f;
  }

  .extra {
    flex: 1;
    padding: 70rpx 70rpx 0;
    .caption {
      width: 440rpx;
      line-height: 1;
      border-top: 1rpx solid #ddd;
      font-size: 26rpx;
      color: #999;
      position: relative;
      text {
        transform: translate(-40%);
        background-color: #fff;
        position: absolute;
        top: -12rpx;
        left: 50%;
      }
    }

    .options {
      display: flex;
      justify-content: center;
      align-items: center;
      margin-top: 70rpx;
      button {
        padding: 0;
        background-color: transparent;
      }
    }

    .icon {
      font-size: 24rpx;
      color: #444;
      display: flex;
      flex-direction: column;
      align-items: center;

      &::before {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 80rpx;
        height: 80rpx;
        margin-bottom: 6rpx;
        font-size: 40rpx;
        border: 1rpx solid #444;
        border-radius: 50%;
      }
    }
    .icon-weixin::before {
      border-color: #06c05f;
      color: #06c05f;
    }
  }
}

.tips {
  position: absolute;
  bottom: 80rpx;
  left: 20rpx;
  right: 20rpx;
  font-size: 22rpx;
  color: #999;
  text-align: center;
}
</style>

获取登录凭证​

前端:调用 wx.login() 接口获取登录凭证(code)。

后端:通过凭证(code)向微信服务器换取用户登录态信息。

<script setup lang="ts">
import { onLoad } from '@dcloudio/uni-app'

// 获取 code 登录凭证
let code = ''
onLoad(async () => {
  const res = await wx.login()
  code = res.code
})
</script>

注意

code 的获取不要在 getphonenumber 事件回调函数调用,否则可能会出现错误!!!

温馨提示

用户登录态信息,不包含用户昵称、性别、手机号码等信息,作用是用于后端服务器与微信服务器通讯。

获取手机号码​

出于安全限制,小程序【规定】想获取用户的手机号,必须由用户主动【点击按钮】并【允许申请】才可获取加密的手机号信息。

前端:提供 open-type 按钮,在事件处理函数中获取加密的手机号信息。

后端:解密手机号信息,把手机号和用户登录态关联在一起。

<script setup lang="ts">
// 获取用户手机号码
const onGetphonenumber: UniHelper.ButtonOnGetphonenumber = (ev) => {
  console.log(ev)
}
</script>

<template>
  <view class="viewport">
    <view class="login">
      <button class="button phone" open-type="getPhoneNumber" @getphonenumber="onGetphonenumber">
        <text class="icon icon-phone"></text>
        手机号快捷登录
      </button>
    </view>
  </view>
</template>

常见问题:

Q:为什么我无法唤起获取手机号的界面?

A:获取手机号功能目前针对非个人开发者,所以个人开发者无法唤起获取手机号界面,详见文档。

为方便开发者开发和体验小程序、小游戏的各种能力,开发者可以申请小程序或小游戏的 测试号,并使用此帐号在开发者工具创建项目进行开发测试,以及真机预览体验。申请测试号的过程非常简单。只需访问 申请地址 ,并使用微信扫描二维码,即可获得为自己分配好的小程序和小游戏测试账号。

项目提供了模拟登录 API 用于练习。

微信登录接口(生产环境) 

接口调用

接口地址:/login/wxMin

请求方式:POST

请求参数:

Body

字段名称是否必须默认值备注
codewx.login 获取
ivgetphonenumber 事件回调获取
encryptedDatagetphonenumber 事件回调获取
// src/services/login.ts

import type { LoginResult } from '@/types/member'
import { http } from '@/utils/http'

type LoginParams = {
  code: string
  encryptedData: string
  iv: string
}
/**
 * 小程序登录
 * @param data 请求参数
 */
export const postLoginWxMinAPI = (data: LoginParams) => {
  return http<LoginResult>({
    method: 'POST',
    url: '/login/wxMin',
    data,
  })
}

 类型声明

// src/types/member.d.ts

/** 小程序登录 登录用户信息 */
export type LoginResult = {
  /** 用户ID */
  id: number
  /** 头像  */
  avatar: string
  /** 账户名  */
  account: string
  /** 昵称 */
  nickname?: string
  /** 手机号 */
  mobile: string
  /** 登录凭证 */
  token: string
}

参考代码

小兔鲜儿项目采用常见的 登录凭证 + 手机号 实现授权登录。

// src/pages/login/login.vue

<script setup lang="ts">
import { postLoginWxMinAPI } from '@/services/login'
import { onLoad } from '@dcloudio/uni-app'

// 获取 code 登录凭证
let code = ''
onLoad(async () => {
  const res = await wx.login()
  code = res.code
})

// 获取用户手机号码
const onGetphonenumber: UniHelper.ButtonOnGetphonenumber = async (ev) => {
  // 获取参数
  const encryptedData = ev.detail.encryptedData!
  const iv = ev.detail.iv!
  // 登录请求
  await postLoginWxMinAPI({ code, encryptedData, iv })
  // 成功提示
  uni.showToast({ icon: 'none', title: '登录成功' })
}
</script>

<template>
  <view class="viewport">
    <view class="login">
      <button class="button phone" open-type="getPhoneNumber" @getphonenumber="onGetphonenumber">
        <text class="icon icon-phone"></text>
        手机号快捷登录
      </button>
    </view>
  </view>
</template>

模拟手机登录(开发环境)

获取手机号功能,目前针对非个人开发者,且完成了认证的小程序开放,详见文档。

温馨提示

为了更好实现登录后续的业务,后端提供了一个内部测试用的接口,只需要传手机号即可实现快捷登录。

请求接口

接口地址:/login/wxMin/simple

请求方式:POST

请求参数:

Body

字段名称是否必须默认值备注
phoneNumber模拟的手机号

该接口跟微信登录接口返回的数据格式是相同的。

/**
 * 小程序登录_内测版
 * @param phoneNumber 模拟手机号码
 */
export const postLoginWxMinSimpleAPI = (phoneNumber: string) => {
  return http<LoginResult>({
    method: 'POST',
    url: '/login/wxMin/simple',
    data: {
      phoneNumber,
    },
  })
}

 参考代码

 <button @tap="onGetphonenumberSimple">
   <text class="icon icon-phone">模拟快捷登录</text>
 </button>
const onGetphonenumberSimple = async () => {
  const res = await postLoginWxMinSimpleAPI("13123456789");
  console.log(res);
  uni.showToast({ icon: "success", title: "登录成功" });
};

用户信息持久化存储​

Pinia 的持久化存储插件在 项目起步 模块已经搭建完成,现在只需要在用户登录成功后,补充 TS 类型声明并保存用户信息即可。

参考代码

Store

// src/stores/modules/member.ts

import type { LoginResult } from '@/types/member'
import { defineStore } from 'pinia'
import { ref } from 'vue'

// 定义 Store
export const useMemberStore = defineStore(
  'member',
  () => {
    // 会员信息
    const profile = ref<LoginResult>() 

    // 保存会员信息,登录时使用
    const setProfile = (val: LoginResult) => {
      profile.value = val
    }

    // 清理会员信息,退出时使用
    const clearProfile = () => {
      profile.value = undefined
    }

    // 记得 return
    return { profile, setProfile, clearProfile }
  },
  {
    // 小程序端配置
    persist: {
      storage: {
        getItem(key) {
          return uni.getStorageSync(key)
        },
        setItem(key, value) {
          uni.setStorageSync(key, value)
        },
      },
    },
  },
)

 登录页

<script setup lang="ts">
import { postLoginWxMinAPI, postLoginWxMinSimpleAPI } from '@/services/login'
import { useMemberStore } from '@/stores'
import type { LoginResult } from '@/types/member'
import { onLoad } from '@dcloudio/uni-app'

// 获取 code 登录凭证
let code = ''
onLoad(async () => {
  const res = await wx.login()
  code = res.code
})

// 获取用户手机号码(企业中写法)
const onGetphonenumber: UniHelper.ButtonOnGetphonenumber = async (ev) => {
  const encryptedData = ev.detail.encryptedData!
  const iv = ev.detail.iv!
  const res = await postLoginWxMinAPI({ code, encryptedData, iv })
  loginSuccess(res.result)
}

// 模拟手机号码快捷登录(开发练习)
const onGetphonenumberSimple = async () => {
  const res = await postLoginWxMinSimpleAPI('13123456789')
  loginSuccess(res.result)
}

const loginSuccess = (profile: LoginResult) => {
  // 保存会员信息
  const memberStore = useMemberStore() 
  memberStore.setProfile(profile) 
  // 成功提示
  uni.showToast({ icon: 'success', title: '登录成功' })
  setTimeout(() => {
    // 页面跳转
    uni.switchTab({ url: '/pages/my/my' })
  }, 500)
}
</script>

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

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

相关文章

SpringBoot虚拟路径映射

要求&#xff1a;访问&#xff1a;127.0.0.1/image/下的文件时&#xff0c;自动映射到真实路径&#xff1a;D:Files\。 virtualFileDepositPath: /image/** realityFileDepositPath: C:\Users\xin\Desktop\imgCreate\Files\ import org.springframework.beans.factory.annota…

整理的10个更好用的画图软件,设计绘图必看!

随着设计工作的不断发展&#xff0c;画图也成了设计师日常的设计工作之一&#xff0c;今天本文整理了10个好用的画图软件&#xff0c;能满足设计师的多种画图需求&#xff0c;一起来看看吧&#xff01; 1、即时设计 即时设计做为一个功能多样的画图软件&#xff0c;不仅可以满…

DPDW01+ 国产锂电池保护电路

描述&#xff1a; DPDW01是一个锂电池保护电路&#xff0c;为避免锂电池因过充电、过放电、电流过大导致电池寿命缩短或电池被损坏而设计的。它具有高精确度的电压检测与时间延迟电路。 主要特点&#xff1a; 工作电流低&#xff1b; 过充检测 4.3V&#xff0c;过充释放 4.0…

Shell - 根据PID过滤进程信息

文章目录 #!/bin/bash #Function: 根据用户输入的PID&#xff0c;过滤出该PID所有的信息 read -p "请输入要查询的PID: " P nps -aux| awk $2~/^$P$/{print $11}|wc -l if [ $n -eq 0 ];thenecho "该PID不存在&#xff01;&#xff01;"exit fi echo "…

TikTok成旺季“主战场”,大促节点一览无遗

随着海外短视频的兴起&#xff0c;拥有10亿月活用户的TikTok已经成为旺季大促的主要营销渠道。从TikTok上的话题标签&#xff0c;可以看出用户对节日及大促节点的关注度&#xff0c;借势飙升的话题流量是大促营销的重要方式之一。数据显示&#xff0c;2023上半年的斋月期间&…

【Java 动态数据统计图】动态X轴二级数据统计图思路案例(动态,排序,动态数组(重点推荐:难))八(130)

需求&#xff1a; 1.有一组数据集合&#xff0c;数据集合中的数据为动态&#xff1b; 举例如下&#xff1a; [{province陕西省, city西安市}, {province陕西省, city咸阳市}, {province陕西省, city宝鸡市}, {province陕西省, city延安市}, {province陕西省, city汉中市}, {pr…

飞腾PSPA可信启动--2 数字签名证书

今天继续第二章&#xff0c;数字签名证书的介绍。 此章节录制了讲解视频&#xff0c;可以在B站进行观看&#xff1a;

PMP - 敏捷 3355

三个核心 产品负责人 负责最大化投资回报&#xff08;ROI&#xff09;&#xff0c;通过确定产品特性&#xff0c;把他们翻译成一个有优先级的列表 为下一个 sprint 决定在这个列表中哪些应该优先级最高&#xff0c;并且不断调整优先级以及调整这个列表 职责是定义需求、定义…

探索软件架构与网络通信协议:构建现代网络应用

文章目录 1. 软件架构&#xff1a;构建应用的基石1.1 C/S架构&#xff1a;客户端/服务器1.2 B/S架构&#xff1a;浏览器/服务器 2. 网络通信协议&#xff1a;构建连接的桥梁2.1 4层模型&#xff1a;数据的分层传输2.2 IP地址与端口号&#xff1a;标识和定位 3. TCP通信&#xf…

Java的数组是啥?

1.数组是啥&#xff1f; 数组是一块连续的内存&#xff0c;用来存储相同类型的数据 &#xff08;1&#xff09;如何定义数组&#xff1f; 1.int[] array {1,2,3,4} new int[]{1,2,3,4};//这里的new是一个关键字&#xff0c;用来创建对象 2.数组就是一个对象 动态初始化 …

[论文笔记]DSSM

引言 这是DSSM论文的阅读笔记,后续会有一篇文章来复现它并在中文数据集上验证效果。 本文的标题翻译过来就是利用点击数据学习网页搜索中深层结构化语义模型,这篇论文被归类为信息检索,但也可以用来做文本匹配。 这是一篇经典的工作,在DSSM之前,通常使用传统机器学习的…

【附安装包】Eplan2022安装教程

软件下载 软件&#xff1a;Eplan版本&#xff1a;2022语言&#xff1a;简体中文大小&#xff1a;1.52G安装环境&#xff1a;Win11/Win10/Win8/Win7硬件要求&#xff1a;CPU2.5GHz 内存4G(或更高&#xff09;下载通道①百度网盘丨64位下载链接&#xff1a;https://pan.baidu.co…

市场中做到低买高卖,其实很简单,FPmarkets澳福10秒教会

所有人都在告诉你&#xff0c;低买高卖就可以在市场大杀四方&#xff0c;但是没有人告诉你&#xff0c;如何在风云莫测的市场中做到低买高卖。其实很简单&#xff0c;FPmarkets澳福10秒钟教会&#xff0c;如果不好使&#xff0c;帮你账户充值1000块钱。 投资者都知道外汇报价在…

Metinfo6.0.0任意文件读取【漏洞复现】

文章目录 1.1、漏洞描述1.2、漏洞等级1.3、影响版本1.4、漏洞复现代码审计漏洞点 1.5、深度利用EXP编写 1.6、漏洞挖掘1.7修复建议 1.1、漏洞描述 漏洞名称&#xff1a;MetInfo任意文件读取 漏洞简介&#xff1a;MetInfo是一套使用PHP和MySQL开发的内容管理系统&#xff0c;其…

C++11 智能指针详解

C 程序设计中使用堆内存是非常频繁的操作&#xff0c;堆内存的申请和释放都由程序员自己管理。程序员自己 管理堆内存可以提高了程序的效率&#xff0c;但是整体来说堆内存的管理是麻烦的&#xff0c;C11 中引入了智能指针的 概念&#xff0c;方便管理堆内存。使用普通指针&…

耕地单目标语义分割实践——Deeplab3+语义分割

耕地单目标语义分割实践系列文章&#xff1a; [1*] 语义分割实践数据集制作—以Sentinel-2 MSI数据为例_doll &#xff5e;CJ的博客-CSDN博客 [2*] 耕地单目标语义分割实践——Pytorch网络过程实现理解_doll &#xff5e;CJ的博客-CSDN博客 [3*] 基于Pytorch的神经网络部分…

RocketMQ-(8-1)-EventBridge-EventBridge 核心概念

RocketMQ EventBridge 核心概念 理解EventBridge中的核心概念&#xff0c;能帮助我们更好的分析和使用EventBridge。本文重点介绍下EventBridge中包含的术语&#xff1a; EventSource&#xff1a;事件源。用于管理发送到EventBridge的事件&#xff0c;所有发送到EventBridge中…

【ES】elasticsearch8.3.3

这里仅实践操作并根据实际问题进行记录笔记。 运行 ES8 我们需要在自己的电脑上安装好 Docker Desktop。接着我们运行如下的命令&#xff1a;出现两个异常&#xff0c;一个是需要使用winpty因为我使用win的docker desktop&#xff0c;另外一个问题是docker启动elasticsearchE…

408考研-数据结构算法-顺序表

数组 如何创建数组 我们以 Java 中创建数组为例&#xff0c;创建语法如下 dataType[] arrName new dataType[size];dataType: 也就是我们数组中元素的数据类型arrName:即数组名size:即数组所能容纳的元素数量new: Java 语言中的关键词 假设我们要创建一个由 10 个元素的数…

基于SSM的在线挂号系统java医院预约管理 jsp源代码Mysql

本项目为前几天收费帮学妹做的一个项目&#xff0c;Java EE JSP项目&#xff0c;在工作环境中基本使用不到&#xff0c;但是很多学校把这个当作编程入门的项目来做&#xff0c;故分享出本项目供初学者参考。 一、项目介绍 基于SSM的在线挂号系统 系统有2权限&#xff1a;前台…