更新记录
1.0.0(2025-11-20)
初步提交
平台兼容性
uni-app(4.71)
| Vue2 | Vue3 | Vue2插件版本 | Chrome | Safari | app-vue | app-vue插件版本 | app-nvue | Android | iOS | 鸿蒙 | 鸿蒙插件版本 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| - | √ | 1.0.0 | × | × | √ | 1.0.0 | - | - | - | 5.0.0 | 1.0.0 |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|
| × | × | × | × | × | × | × | × | × | × | × |
uni-app x(4.71)
| Chrome | Safari | Android | iOS | 鸿蒙 | 微信小程序 |
|---|---|---|---|---|---|
| - | - | - | - | - | - |
harmony-auth
华为账号登录 UTS 插件 - 支持 HarmonyOS
📦 插件信息
- 插件ID:
harmony-auth - 版本:
1.0.0 - 平台支持: HarmonyOS (app-harmony)
- 类型: UTS 原生插件
🚀 功能特性
-
获取匿名手机号
- 获取华为账号绑定的脱敏手机号(如:138****1234)
- 用于登录页面展示
- 使用
HuaweiIDProviderAPI
-
华为账号一键登录
- 获取华为账号授权码
- 支持后端验证登录
- 使用
account_authenticationAPI
-
协议校验与用户体验
- 登录前协议同意检查
- 防重复登录保护
- 友好的错误提示
🔧 集成与配置
1. 安装插件
将插件放入 uni_modules/harmony-auth 目录。
2. 华为开发者配置
在华为开发者后台配置应用指纹和包名。
📖 使用方法
1. 导入插件
// 推荐方式:ES6 导入
import { getQuickLoginAnonymousPhone, getAuthorizationCode } from '@/uni_modules/harmony-auth';
// 或使用工具类封装
import HarmonyLoginUtil from '@/utils/harmonyLoginUtil.js';
2. 获取匿名手机号
异步方式(推荐):
// 在页面加载时获取
const loadHarmonyPhoneNumber = async () => {
try {
const phone = await getQuickLoginAnonymousPhone();
if (phone) {
console.log('匿名手机号:', phone); // 138****1234
// 显示在登录页面
}
} catch (error) {
console.error('获取失败:', error);
}
};
使用工具类:
import HarmonyLoginUtil from '@/utils/harmonyLoginUtil.js';
const phone = await HarmonyLoginUtil.getAnonymousPhone();
3. 页面集成原生登录按钮
Vue 页面示例(login.vue):
<template>
<view>
<!-- 显示匿名手机号 -->
<view v-if="quickLoginAnonymousPhone">
{{ quickLoginAnonymousPhone }}
</view>
<!-- 华为一键登录按钮 -->
<harmonyButton
:checked="agreementVal"
:triggerLogin="triggerHarmonyLogin"
:enableNetworkCheck="false"
@harmonyLogin="handleHarmonyLogin"
/>
<!-- 协议组件 -->
<agree
v-model="agreementVal"
ref="agreeRef"
@confirm="handleAgreeConfirm"
/>
</view>
</template>
<script setup>
import harmonyButton from "./components/harmonyButton.vue";
import agree from "./components/agree.vue";
import HarmonyLoginUtil from "@/utils/harmonyLoginUtil.js";
import useUserStore from "@/stores/user.js";
const quickLoginAnonymousPhone = ref("");
const agreementVal = ref(false);
const agreeRef = ref(null);
const triggerHarmonyLogin = ref(false);
const isLoggingIn = ref(false);
// 页面加载时获取匿名手机号
onLoad(() => {
loadHarmonyPhoneNumber();
});
const loadHarmonyPhoneNumber = async () => {
const phone = await HarmonyLoginUtil.getAnonymousPhone();
if (phone) {
quickLoginAnonymousPhone.value = phone;
}
};
// 用户同意协议后触发登录
const handleAgreeConfirm = () => {
isLoggingIn.value = true;
triggerHarmonyLogin.value = true;
setTimeout(() => {
triggerHarmonyLogin.value = false;
}, 1000);
};
// 处理登录结果
const handleHarmonyLogin = async (result) => {
if (result.needAgreement) {
agreeRef.value.openPopup();
return;
}
if (result.success && result.authCode) {
// 调用后端 API
await useUserStore().harmonyOneTouchLogin(result.authCode);
uni.switchTab({ url: '/pages/index/index' });
} else {
uni.showToast({
title: result.error || '登录失败',
icon: 'none'
});
}
isLoggingIn.value = false;
};
</script>
4. 封装工具类(harmonyLoginUtil.js)
import { getQuickLoginAnonymousPhone } from '@/uni_modules/harmony-auth';
class HarmonyLoginUtil {
constructor() {
this.isLoggingIn = false;
this.bundleName = 'com.num.phonemanager.parent.hm';
}
// 获取匿名手机号
async getAnonymousPhone() {
try {
const phone = await getQuickLoginAnonymousPhone();
return phone || '';
} catch (error) {
console.error('获取匿名手机号异常:', error);
return '';
}
}
// 重置登录状态
resetLoginState() {
this.isLoggingIn = false;
}
}
export default new HarmonyLoginUtil();
5. 华为登录按钮组件(harmonyButton.vue)
<template>
<embed
tag="quickloginbutton"
:options="quickloginparams"
@quick_login_response="onQuickLoginResponse">
</embed>
</template>
<script setup>
import { ref, computed, watch } from 'vue';
import { dealAllError, ErrorCode } from '@/uni_modules/harmony-auth';
const props = defineProps({
checked: { type: Boolean, default: false },
triggerLogin: { type: Boolean, default: false }
});
const emit = defineEmits(['harmonyLogin']);
const isDisabled = ref(false);
const noNetworkCount = ref(0);
const isContinueLogin = ref(false);
// 监听触发登录
watch(() => props.triggerLogin, (newVal) => {
if (newVal && props.checked) {
isContinueLogin.value = true;
setTimeout(() => {
isContinueLogin.value = false;
}, 500);
}
});
const quickloginparams = computed(() => ({
noNetCnt: noNetworkCount.value,
isUserAgree: props.checked,
isContinueLogin: isContinueLogin.value,
isDisabled: isDisabled.value
}));
const onQuickLoginResponse = (event) => {
const detail = event.detail;
// 登录成功
if (detail.quickLoginResponse) {
emit('harmonyLogin', {
success: true,
authCode: detail.authCode
});
}
// 登录失败
if (detail.error) {
emit('harmonyLogin', {
success: false,
error: detail.error.message
});
}
};
</script>
6. 后端接口调用(user.js store)
// 华为账号一键登录
harmonyOneTouchLogin(code) {
if (this.isLoggingIn) {
return Promise.reject(new Error('登录中,请勿重复操作'));
}
this.isLoggingIn = true;
return new Promise((resolve, reject) => {
uni.showLoading({ title: '登录中', mask: true });
harmonyLoginApi({ authCode: code })
.then(async (res) => {
if (res.data) {
this.token = res.data.token;
this.userInfo = res.data.userInfo;
uni.setStorageSync('token', this.token);
uni.setStorageSync('userInfo', this.userInfo);
resolve(res);
}
})
.catch((error) => {
reject(error);
})
.finally(() => {
uni.hideLoading();
this.isLoggingIn = false;
});
});
}
📝 接口定义
详见 uni_modules/harmony-auth/utssdk/interface.uts:
AuthOptions(授权选项)
type AuthOptions = {
bundleName?: string; // 应用包名
forceLogin?: boolean; // 是否强制登录
success?: (res: AuthSuccessResult) => void;
fail?: (err: AuthErrorResult) => void;
complete?: () => void;
}
PhoneSuccessResult(手机号结果)
type PhoneSuccessResult = {
anonymousPhone: string; // 匿名手机号 (如: 138****1234)
errCode: number;
errMsg: string;
}
AuthSuccessResult(授权成功结果)
type AuthSuccessResult = {
code: string; // 授权码
authCode: string; // 授权码(兼容字段)
state?: string;
errCode: number;
errMsg: string;
}
🔍 错误码与处理
详见 conf/harmonyConfig.js:
| 错误码 | 含义 | 处理建议 |
|---|---|---|
*** |
网络错误 | 检查网络连接 |
*** |
未同意协议 | 弹出协议弹窗 |
*** |
未登录华为账号 | 引导用户登录系统账号 |
*** |
用户取消授权 | 提示用户可使用其他方式登录 |
*** |
服务异常 | 提示稍后重试 |
错误信息获取:
import { getHarmonyErrorMessage } from '@/conf/harmonyConfig.js';
const errorMsg = getHarmonyErrorMessage(errorCode);
uni.showToast({ title: errorMsg, icon: 'none' });
💡 最佳实践
1. 协议校验流程
// 未同意协议时,先弹出协议弹窗
if (!agreementVal.value) {
agreeRef.value.openPopup();
return;
}
// 用户点击"同意并继续"后,自动触发登录
const handleAgreeConfirm = () => {
agreementVal.value = true;
triggerHarmonyLogin.value = true;
};
2. 防重复登录
// 在 store 中使用标识
if (this.isLoggingIn) {
return Promise.reject(new Error('登录中,请勿重复操作'));
}
this.isLoggingIn = true;
// 登录结束后重置
.finally(() => {
this.isLoggingIn = false;
});
3. 按钮禁用控制
// 登录期间禁用所有登录按钮
const isLoggingIn = ref(false);
// 在模板中
<uv-button
:disabled="isLoggingIn"
@click="handleLogin">
</uv-button>
4. 错误处理
const handleHarmonyLogin = async (result) => {
if (result.needAgreement) {
agreeRef.value.openPopup();
return;
}
if (!result.success) {
uni.showToast({
title: result.error || '登录失败',
icon: 'none'
});
return;
}
// 调用后端 API
await useUserStore().harmonyOneTouchLogin(result.authCode);
};
🔧 技术实现
核心 API
@kit.AccountKit- 华为账号服务HuaweiIDProvider- 华为ID提供者AuthenticationController- 认证控制器LoginWithHuaweiIDButton- 原生登录按钮组件
项目结构
uni_modules/harmony-auth/
├── utssdk/
│ ├── app-harmony/
│ │ ├── index.uts # 主要 API 实现
│ │ └── button.ets # 原生登录按钮组件
│ └── interface.uts # 类型定义
├── readme.md # 使用文档
└── changelog.md # 更新日志
项目集成文件:
├── utils/harmonyLoginUtil.js # 工具类封装
├── conf/harmonyConfig.js # 配置与错误码
├── pagesMy/login/
│ ├── login.vue # 登录页面
│ └── components/
│ ├── harmonyButton.vue # 华为登录按钮组件
│ └── agree.vue # 协议组件
└── stores/user.js # 状态管理
📚 参考文档
⚠️ 注意事项
必要条件
-
平台限制
- 仅支持 HarmonyOS 平台
- 需使用
#ifdef APP-HARMONY条件编译
-
权限配置
- 在
manifest.json中配置ohos.permission.INTERNET
- 在
-
开发者配置
- 在华为开发者后台配置应用指纹
- 配置正确的包名(bundleName)
-
用户要求
- 用户必须在设备上登录华为账号
- 首次使用需用户同意用户协议
开发建议
-
协议校验
- 登录前必须检查用户是否同意协议
- 未同意时弹出协议弹窗,不自动触发登录
-
防重复登录
- 使用
isLoggingIn标识防止重复提交 - 登录期间禁用所有登录按钮
- 使用
-
错误处理
- 使用
getHarmonyErrorMessage()获取友好提示 - 区分不同错误类型,给予不同处理方案
- 使用
-
网络检测配置
enableNetworkCheck: false(推荐):使用 Vue 层的全局提示框$jd_toast,UI 风格统一enableNetworkCheck: true:使用原生层的对话框showAlertDialog,系统原生风格- 建议关闭原生网络检测,避免重复提示
-
用户体验
- 页面加载时获取并显示匿名手机号
- 登录失败时提供明确的错误提示
- 提供其他登录方式作为备选
常见问题
Q: 获取不到匿名手机号?
- 检查用户是否登录华为账号
- 确认应用指纹配置正确
Q: 登录时提示未同意协议?
- 检查
isUserAgree参数是否正确传递 - 确保用户点击"同意并继续"后再触发登录
Q: 未勾选协议点击登录,同意协议后网络异常怎么办?
- ✅ 已正确处理:网络异常会弹出提示,并重置登录状态
- ✅ 用户可以在网络恢复后重新点击登录按钮
- ✅ 不需要重新勾选协议(协议状态已保存)
Q: 授权码获取失败?
- 使用原生
LoginWithHuaweiIDButton组件方式 - 不要直接调用
getAuthorizationCode()方法
Q: 如何测试?
- 使用真机,确保已登录华为账号
- 在开发者后台配置测试环境应用指纹
📋 更新日志
详见 uni_modules/harmony-auth/changelog.md
📞 技术支持
如需更多接口和参数说明,请:
- 查阅插件源码
- 参考官方文档
- 查看项目中的实际调用示例
版本: 1.0.0 | 更新日期: 2024-01-18

收藏人数:
购买源码授权版(
试用
赞赏(0)
下载 0
赞赏 0
下载 11316747
赞赏 1810
赞赏
京公网安备:11010802035340号