1.问题描述:
接入微信登录后,还要接华为登录吗?
解决方案:
为了帮助用户省去多次输入不同应用账号登录的繁琐过程,我们为HarmonyOS应用和元服务提供了使用华为账号快捷登录的能力。提交至华为应用市场的HarmonyOS应用和元服务,需要遵循如下规范:
如果开发者应用支持用户使用第三方账号登录,则该应用需提供华为账号登录选项。用户可通过华为账号快捷地登录您的应用,并获得华为账号的安全配置。
其中登录场景全部满足以下三点时,华为账号登录为必选:
- 接入了第三方登录方式(如微信登录、QQ登录)。
- 应用和三方账号CP非同一关联主体(如qq音乐接入微信登录,就属于同一关联主体)。
- 不涉及使用公民真实身份信息来鉴定用户身份。其中公民真实身份信息包括中国大陆居民身份证、中华人民共和国外国人永久居留身份证、护照、台湾居民来往大陆通行证、台湾居民居住证、港澳居民来往内地通行证、港澳居民居住证、香港身份证、澳门身份证、军人身份证。
2.问题描述:
华为账号一键登录无法获取手机号。
解决方案:
在华为账号一键登录场景下,获取匿名手机号为空或无法获取到明文手机号时,建议通过以下步骤排查解决:
- 申请权限待生效,权限申请后需要24小时后生效或将调试设备系统时间向后调整24小时后重试。
- 华为账号未绑定手机号,该异常场景应用需要展示其他登录方式。
- 使用华为账号一键登录服务的账号必须是中国境内(不包含中国香港、中国澳门、中国台湾)华为账号。
- 应用服务端获取华为账号绑定号码时,该服务器必须部署在中国境内(不包含中国香港、中国澳门、中国台湾),参考华为账号一键登录约束与限制。
- 确认权限申请成功后,确认scope参数是否符合预期,详情可参考一键登录客户端开发。
- 开发者开启了代码混淆,quickLoginAnonymousPhone(匿名手机号)属性需要配置混淆白名单防止被混淆,参考混淆选项配置指导中使用-keep-property-name保留属性名称。
3.问题描述:
一键登录是否支持H5接入?
解决方案:
支持。当前渲染H5页面依赖的是ArkWeb能力,将一键登录Button直接渲染到H5页面,依赖的是ArkWeb同层渲染(当非系统框架的UI组件功能或性能不如系统组件时,可使用同层渲染技术,通过ArkUI组件渲染这些组件),应用侧(arkTs)与前端页面(H5)的数据交互可参考建立应用侧与前端页面数据通道。
完整demo参考:基于H5使用 Account Kit 提供的华为账号一键登录 Button 组件登录流程。
4.问题描述:
华为账号一键登录接入过程中,客户端获取到AuthorizationCode后,需要传到服务端,通过服务端调用华为账号接口获取用户信息。AuthorizationCode传到服务端调用华为账号接口这部分功能,是否可以在客户端直接实现?
解决方案:
在HarmonyOS开发中,华为账号一键登录通常需要通过应用服务器来获取业务登录凭证,不建议直接在客户端获取。以下是具体原因:
-
安全性考虑
防止敏感信息泄露:业务登录凭证(如Access Token)是敏感信息,直接在客户端获取和存储可能会增加被恶意获取的风险。
-
业务逻辑的实现
用户关联和注册:服务器可以根据获取到的用户信息(如UnionID、OpenID、手机号等)完成用户关联、注册等业务逻辑。
-
客户端的限制
无法处理复杂逻辑:客户端处理能力有限,不适合处理复杂的业务逻辑和安全策略。
综上所述,不建议在客户端完成此部分,推荐在服务端实现。
5.问题描述:
应用接入华为账号一键登录,出现部分华为用户登录时页面白屏。
解决方案:
如果用户的华为账号为邮箱账号,并且没有绑定手机账号,此时quickLoginAnonymousPhone调用AuthorizationWithHuaweiIDRequest授权请求获取匿名手机号,手机号为空。此时需要进行空值判断并引导用户使用其他登录方式,否则使用空手机号进行后续登录处理,可能会导致页面空白,登录失败。
6.问题描述:
登录同一个华为账号的不同设备上,同一个应用的token是相同的吗?
解决方案:
不同。token是与设备绑定的标识符。即使使用同一华为账号,在不同设备上安装同一应用时,系统会为每个设备生成独立的token。
7.问题描述:
单工程多product开发模式,一键登录的metadata如何分开配置?
解决方案:
通过HarmonyOS的扩展构建功能,开发者可以在编译阶段动态配置模块的参数。具体来说:
全局配置:若配置信息涉及多个模块或需要跨模块操作(如根据产物名称动态调整参数),建议将配置逻辑放在项目根目录下的hvigorfile.ts文件中。
模块级配置:若仅需配置单个模块的metadata参数,且无需跨模块操作,则可以直接在模块目录中进行配置。
详细步骤:
1、需要获取产物名称,根据产物配置对应的模块参数,因此应在最外层配置hvigorfile.ts文件。
2、根据如下代码获取应用配置参数,获取其中配置的产物名称。
const appNode: HvigorNode = getNode(__filename);const appContext = appNode.getContext(OhosPluginId.OHOS_APP_PLUGIN) as OhosAppContext;const bundleProduct = appContext.getCurrentProduct()const productName = bundleProduct['productName']
3、使用subNodes接口获取所有模块的环境信息,然后通过getContext接口分别获取hap包和hsp包配置信息。
const hapContext = hapNode.getContext(OhosPluginId.OHOS_HAP_PLUGIN) as OhosHapContext;const hspContext = hapNode.getContext(OhosPluginId.OHOS_HSP_PLUGIN) as OhosHspContext;
4、根据第2步获取的包名和第三步获取到的环境信息,使用getModuleJsonOpt获取对应模块下的module.json5配置,修改后,使用setModuleJsonOpt将修改后的配置信息写入。
if ('xxx' === moduleName) {const moduleJsonOpt = hapContext?.getModuleJsonOpt()console.log('moduleJsonOpt:', moduleJsonOpt);if (moduleJsonOpt) {moduleJsonOpt['module']['metadata'] = productName === 'xxxxxx' ?[{ "name": "client_id", "value": "xxxxxxxxx" }] : [{ "name": "client_id", "value": "xxxxxxxxx" }]// 将obj对象设置回上下文对象以使能到构建的过程与结果中hapContext.setModuleJsonOpt(moduleJsonOpt);}}
总体配置文件hvigorfile.ts,配置如下:
import { appTasks, hapTasks, OhosHapContext, OhosAppContext, OhosPluginId } from '@ohos/hvigor-ohos-plugin';import { createJsFile } from './plugin/pluginCreateJsFile';import { getNode, hvigor, HvigorNode } from '@ohos/hvigor'hvigor.nodesEvaluated(() => {const appNode: HvigorNode = getNode(__filename);const appContext = appNode.getContext(OhosPluginId.OHOS_APP_PLUGIN) as OhosAppContext;const bundleProduct = appContext.getCurrentProduct()const productName = bundleProduct['productName']appNode.subNodes((hapNode: HvigorNode) => {// 获取hap模块上下文信息const hapContext = hapNode.getContext(OhosPluginId.OHOS_HAP_PLUGIN) as OhosHapContext;const moduleName = hapContext?.getModuleName()const modulePath = hapContext?.getModulePath()if ('xxx' === moduleName) {const moduleJsonOpt = hapContext?.getModuleJsonOpt()console.log('moduleJsonOpt:', moduleJsonOpt);if (moduleJsonOpt) {moduleJsonOpt['module']['metadata'] = productName === 'xxxx' ?[{ "name": "client_id", "value": "xxxxx" }] : [{ "name": "client_id", "value": "xxxxx" }]// 将obj对象设置回上下文对象以使能到构建的过程与结果中hapContext.setModuleJsonOpt(moduleJsonOpt);}}});});export default {system: appTasks,plugins: [createJsFile(),]}