uniapp手机号一键登录保姆级教程(包含前端和后端)
目录
- 前置条件
- 创建uniapp项目并关联uniClound云空间
- 开启一键登录模块并开通一键登录服务
- 编写云函数并上传部署
- 获取手机号流程
- (第一种) 前端直接调用云函数获取手机号
- (第三种)后台调用云函数获取手机号
- 错误码
- 常见问题
前置条件
- 手机安装有sim卡
- 手机开启数据流量(与wifi无关,不要求关闭wifi,但数据流量不能禁用。)
- 开通uniCloud服务(但不要求所有后台代码都使用uniCloud)
创建uniapp项目并关联uniClound云空间
新建uniapp项目,勾选下面“启用uniClound”,选择其中一个云服务商即可。
如果在已有项目中启用uniClound,可直接右键项目文件夹,选择“创建uniClound云开发环境”。
创建好uniClound云开发环境后,会在项目目录中增加一个“uniClound”的文件夹,右键该文件夹,选择“关联云服务空间或项目”。
如果还没有相应的云服务空间,可以选择新建云服务空间
打开uniClound官网开发者后台,选择“新建服务空间”
目前阿里云还是免费的,直接选择“立即购买”,
购买之后,在前端再次刷新云服务空间,即可看到新购的服务空间,选择并关联即可。
开启一键登录模块并开通一键登录服务
打开项目的“manifest.json”,选择“App模块配置”,勾选“OAuth(登录授权)”
在uniClound官网开发者后台开通一键登录服务,然后选择“账户信息”,并完成充值。
余额充值
充值之后,打开“应用管理”,点击添加应用
填写应用相关信息后,点击“提交申请”,审核可能会需要几个小时时间
如果还没有Android包名,按图点击前往创建。
会跳到应用列表页,点击自己的应用名称进入详情。
选择“Android云端证书”,选择创建证书
点击证书详情,记住“MD5”,“SHA1”和“SHA256”。
点击“各平台信息”,完善上面的“MD5”,“SHA1”和“SHA256”等信息即可。
编写云函数并上传部署
回到项目,右键“cloundfunctions”,新建云函数/云对象,取名“getPhoneNumber”(函数名可自定义)。
打开“getPhoneNumber”文件夹下的“index.js”,编写如下代码。
复制下面代码,修改成自己的DClound appid即可
'use strict';
exports.main = async (event, context) => {// event里包含着客户端提交的参数let data = await uniCloud.getPhoneNumber({appid: '__UNI__AAAAAA', // 替换成自己开通一键登录的应用的DCloud appid,使用callFunction方式调用时可以不传(会自动取当前客户端的appid),如果使用云函数URL化的方式访问必须传此参数provider: 'univerify',access_token: event.access_token,openid: event.openid})return data//返回的data里包含手机号
}
自HBuilderX
3.4.0起,一键登录相关功能移至扩展库uni-cloud-verify内。在一段时间内无论开发者是否使用扩展库云函数都可以正常使用uniCloud.getPhoneNumber。HBuilderX 3.4.0及之后的版本上传云函数时如果没有指定使用uni-cloud-verify扩展库的云函数将无法调用uniCloud.getPhoneNumber接口。关于扩展库的说明见:云函数扩展库
在云函数的package.json内添加uni-cloud-verify的引用即可为云函数启用此扩展,无需做其他调整,完整的package.json示例如下:
{"name": "univerify","extensions": {"uni-cloud-verify": {} // 启用一键登录扩展,值为空对象即可}
}
写完后,右键“cloudfunctions”,上传所有云函数。
获取手机号流程
(第一种) 前端直接调用云函数获取手机号
这里写一个简单的登录功能。
<template><view><button @tap="goLogin">手机号一键登录</button></view>
</template><script setup>//手机号一键登录事件function goLogin() {uni.login({provider: 'univerify',univerifyStyle: { // 自定义登录框样式//参考`univerifyStyle 数据结构`"fullScreen": true, // 是否全屏显示,默认值: false"title": '快速登录',"backgroundColor": "#ffffff", // 授权页面背景颜色,默认值:#ffffff"icon": {"path": "../../static/my/头像.png" // 自定义显示在授权框中的logo,仅支持本地图片 默认显示App logo},"phoneNum": {"color": "#000000", // 手机号文字颜色 默认值:#000000"fontSize": "18" // 手机号字体大小 默认值:18},"slogan": {"color": "#8a8b90", // slogan 字体颜色 默认值:#8a8b90"fontSize": "12" // slogan 字体大小 默认值:12},// 一键登录"authButton": {"normalColor": "#3479f5", // 授权按钮正常状态背景颜色 默认值:#3479f5"highlightColor": "#2861c5", // 授权按钮按下状态背景颜色 默认值:#2861c5(仅ios支持)"disabledColor": "#73aaf5", // 授权按钮不可点击时背景颜色 默认值:#73aaf5(仅ios支持)"textColor": "#ffffff", // 授权按钮文字颜色 默认值:#ffffff"title": "本机号码一键登录" // 授权按钮文案 默认值:“本机号码一键登录”},// 其他登录方式"otherLoginButton": {"visible": "true", // 是否显示其他登录按钮,默认值:true"normalColor": "#f8f8f8", // 其他登录按钮正常状态背景颜色 默认值:#f8f8f8"highlightColor": "#dedede", // 其他登录按钮按下状态背景颜色 默认值:#dedede"textColor": "#000000", // 其他登录按钮文字颜色 默认值:#000000"title": "密码登录", // 其他登录方式按钮文字 默认值:“其他登录方式”"borderWidth": "1px", // 边框宽度 默认值:1px(仅ios支持)"borderColor": "#c5c5c5" //边框颜色 默认值: #c5c5c5(仅ios支持)},// 自定义按钮登录方式"buttons": { // 仅全屏模式生效,配置页面下方按钮 (3.1.14+ 版本支持) "iconWidth": "45px", // 图标宽度(高度等比例缩放) 默认值:45px "list": [{"provider": "apple","iconPath": "/static/test.jpg", // 图标路径仅支持本地图片 },{"provider": "weixin","iconPath": "/static/test.jpg",}]},"privacyTerms": {"defaultCheckBoxState": "true", // 条款勾选框初始状态 默认值: true"textColor": "#8a8b90", // 文字颜色 默认值:#8a8b90"termsColor": "#1d4788", // 协议文字颜色 默认值: #1d4788"prefix": "我已阅读并同意", // 条款前的文案 默认值:“我已阅读并同意”"suffix": "并使用本机号码登录", // 条款后的文案 默认值:“并使用本机号码登录”"fontSize": "12", // 字体大小 默认值:12,"privacyItems": [// 自定义协议条款,最大支持2个,需要同时设置url和title. 否则不生效{"url": "https://", // 点击跳转的协议详情页面"title": "用户服务协议" // 协议名称}]}},success(res) { // 登录成功console.log(res);let openid = res.authResult.openid; //拿到openidlet access_token = res.authResult.access_token; //拿到access_tokenconsole.log(openid)console.log(access_token)// 在得到access_token和openid后,通过callfunction调用云函数uniCloud.callFunction({name: "getPhoneNumber",data: {openid,access_token}}).then(res1 => {console.log("获取成功");console.log(res1);// 获取用户的手机号let phoneNumber = res1.result.phoneNumber;//接下来就进行你自己的操作//...//...}).catch((err) => {// 执行失败后的操作//...//...})},// 当用户点击自定义按钮时,会触发uni.login的fail回调[点击其他登录方式,可以跳转页面,或执行事件]fail(res) { // 登录失败console.log(res.code)if (res.code == "30002") {console.log('账号密码登录');}}})}
</script>
(第三种)后台调用云函数获取手机号
后台代码
// 以nodejs为例
const crypto = require('crypto')const secret = 'your-secret-string' // 自己的密钥不要直接使用示例值,且注意不要泄露
const hmac = crypto.createHmac('sha256', secret);// 自有服务器生成签名,并以GET方式发送请求
const params = {access_token: 'xxx', // 客户端传到自己服务器的参数openid: 'xxx'
}
// 字母顺序排序后拼接签名串
const signStr = Object.keys(params).sort().map(key => {return `${key}=${params[key]}`
}).join('&')
hmac.update(signStr);
const sign = hmac.digest('hex')
// 最终请求如下链接,其中https://xxxx/xxx为云函数Url化地址
// https://xxxx/xxx?access_token=xxx&openid=xxx&sign=${sign} 其中${sign}为上一步得到的sign值
云函数Url化地址设置可修改。
对应云函数“index.js”,修改如下:
// 云函数验证签名,此示例中以接受GET请求为例作演示
const crypto = require('crypto')
exports.main = async function (event){const secret = 'your-secret-string' // 自己的密钥不要直接使用示例值,且注意不要泄露const hmac = crypto.createHmac('sha256', secret);let params = event.queryStringParametersconst sign = params.signdelete params.signconst signStr = Object.keys(params).sort().map(key => {return `${key}=${params[key]}`}).join('&')hmac.update(signStr);if(sign!==hmac.digest('hex')){throw new Error('非法访问')}const {access_token,openid} = paramsconst res = await uniCloud.getPhoneNumber({provider: 'univerify',appid: 'xxx', // DCloud appidaccess_token: event.queryStringParameters.access_token,openid: event.queryStringParameters.openid})// 返回手机号给自己服务器return res
}
注意:云函数修改之后,右键“getPhoneNumber”,上传部署才能生效。
前端代码:
uni.login({provider: 'univerify', success: function(res) {console.log('LOGINres----', res);let data = {accessToken: res.authResult.access_token,openId: res.authResult.openid}console.log('data----', data);uni.request({url: 'https://xxxxx/xxx', //自己应用服务器的请求地址data: {data: JSON.stringify(data)},method: "POST",header: {"content-type": "application/x-www-form-urlencoded"},success: function(r) {console.log('结果---', r)//获取登录成功的token,并保存在前端},fail: function(err) {console.log('err--', err);}})},fail: function(err) {console.log('err', err);}})
错误码
30004
login:fail -20102其他错误 Android:
1.确认开发者中心一键登录已添加应用并审核通过
2.检查开通一键登录时使用的签名证书和云打包时使用的签名证书一致
常见问题
- 后台请求云函数获取手机号报错:Error: Parameter access_token is required
(1)首先检查后端是否传了access_token。
(2)检查前端云函数的“index.js”的openid和access_token的获取方式要加上“queryStringParameters”。并确保修改“index.js”文件后要右键上传部署才生效。
参考:
1.官网:https://uniapp.dcloud.net.cn/univerify.html
相关文章:

uniapp手机号一键登录保姆级教程(包含前端和后端)
目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号(第三种)后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...
JavaScript 数据类型详解
JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型(Primitive) 和 对象类型(Object) 两大类,共 8 种(ES11): 一、原始类型(7种) 1. undefined 定…...

【Linux】Linux 系统默认的目录及作用说明
博主介绍:✌全网粉丝23W,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...

RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...

搭建DNS域名解析服务器(正向解析资源文件)
正向解析资源文件 1)准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2)服务端安装软件:bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...
【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制
使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下,限制某个 IP 的访问频率是非常重要的,可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案,使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...
腾讯云V3签名
想要接入腾讯云的Api,必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口,但总是卡在签名这一步,最后放弃选择SDK,这次终于自己代码实现。 可能腾讯云翻新了接口文档,现在阅读起来,清晰了很多&…...
MySQL JOIN 表过多的优化思路
当 MySQL 查询涉及大量表 JOIN 时,性能会显著下降。以下是优化思路和简易实现方法: 一、核心优化思路 减少 JOIN 数量 数据冗余:添加必要的冗余字段(如订单表直接存储用户名)合并表:将频繁关联的小表合并成…...

mac 安装homebrew (nvm 及git)
mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用: 方法一:使用 Homebrew 安装 Git(推荐) 步骤如下:打开终端(Terminal.app) 1.安装 Homebrew…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...

【C++进阶篇】智能指针
C内存管理终极指南:智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...
CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝
目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为:一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...
站群服务器的应用场景都有哪些?
站群服务器主要是为了多个网站的托管和管理所设计的,可以通过集中管理和高效资源的分配,来支持多个独立的网站同时运行,让每一个网站都可以分配到独立的IP地址,避免出现IP关联的风险,用户还可以通过控制面板进行管理功…...
scikit-learn机器学习
# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...
C#学习第29天:表达式树(Expression Trees)
目录 什么是表达式树? 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持: 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...

接口自动化测试:HttpRunner基础
相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具,支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议,涵盖接口测试、性能测试、数字体验监测等测试类型…...

STM32HAL库USART源代码解析及应用
STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...
CSS | transition 和 transform的用处和区别
省流总结: transform用于变换/变形,transition是动画控制器 transform 用来对元素进行变形,常见的操作如下,它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...
Go语言多线程问题
打印零与奇偶数(leetcode 1116) 方法1:使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...
GitHub 趋势日报 (2025年06月06日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...

【JVM】Java虚拟机(二)——垃圾回收
目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四ÿ…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...

并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...
Webpack性能优化:构建速度与体积优化策略
一、构建速度优化 1、升级Webpack和Node.js 优化效果:Webpack 4比Webpack 3构建时间降低60%-98%。原因: V8引擎优化(for of替代forEach、Map/Set替代Object)。默认使用更快的md4哈希算法。AST直接从Loa…...
Redis:现代应用开发的高效内存数据存储利器
一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发,其初衷是为了满足他自己的一个项目需求,即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源,Redis凭借其简单易用、…...
MySQL 8.0 事务全面讲解
以下是一个结合两次回答的 MySQL 8.0 事务全面讲解,涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容,并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念(ACID) 事务是…...

免费数学几何作图web平台
光锐软件免费数学工具,maths,数学制图,数学作图,几何作图,几何,AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...

基于Springboot+Vue的办公管理系统
角色: 管理员、员工 技术: 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能: 该办公管理系统是一个综合性的企业内部管理平台,旨在提升企业运营效率和员工管理水…...

Linux nano命令的基本使用
参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时,显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...