做元服务时,除了基础登录授权,手机号一键登录、实名状态检查、隐私协议同意判断都是高频需求。ASCF 把这些能力归到“隐私”分类,与“账号”类 API 分开。很多开发者会先找 getUserInfo,以为它能直接拿手机号,实际上手机号在另一个 API 里,通道也不同。下面按实际开发链路梳理这些隐私 API 的用法、配置和踩坑点。
先分清 getUserInfo 与 getUserProfile
has.getUserInfo 和 has.getUserProfile 都能获取用户信息,但机制不同。getUserProfile 直接返回昵称和头像 URL,前端可直接展示;getUserInfo 返回 code,需要发给服务端换取头像昵称。也就是说,如果只是展示用户信息,用 getUserProfile 更简单;如果服务端还要存储或做业务逻辑,则用 getUserInfo。getUserInfo 需要在 openHarmony/app.json5 的 client.privacyApi 下配置 getUserInfo: true,否则 API 不会注册,调用会报方法不存在。getUserProfile 不需要 privacyApi 配置,但要求 HarmonyOS SDK >= 6.0.0,版本门槛更高。
- has.getUserInfo({
- success: (res) => {
- console.info('code:', res.code);
- // 把 code 发给服务端,服务端调华为接口获取头像昵称
- },
- fail: (err) => {
- console.error('获取失败:', err);
- }
- });
复制代码
手机号必须走服务端换号
has.getPhoneNumber 返回的并不是手机号本身,而是 code。前端要把 code 发到自己的服务器,服务器再用 access_token + code 调华为接口,才能拿到手机号并返回给前端。这个设计出于安全考虑,前端不能直接拿手机号。配置方式与 getUserInfo 类似,需要在 app.json5 的 client.privacyApi 中配置 getPhoneNumber: true。手机号 code 有时效,拿到后应尽快发给服务端处理。
- has.getPhoneNumber({
- success: (res) => {
- console.info('手机号 code:', res.code);
- // 把 code 发给服务端,服务端调华为接口获取手机号
- },
- fail: (err) => {
- console.error('获取失败:', err);
- }
- });
复制代码
手机号获取完整链路可以概括为:用户点击手机号登录,前端调 has.getPhoneNumber 得到 code,把 code 发给自己的服务器,服务器用 code 调华为接口获取手机号,然后返回登录结果,前端保存登录态并跳转。这个流程和微信小程序的 getPhoneNumber 几乎一样。服务端环节主要是先获取 OAuth 的 access_token,再用 access_token + code 调手机号接口;获取用户信息也是类似,用 access_token + code 调用户信息接口。华为有现成 SDK,不需要自己拼 HTTP 请求。
实名状态查询与版本判断
has.getRealNameStatus 用于查询当前用户实名状态。它的起始版本是 1.0.20,依赖 HarmonyOS SDK >= 6.0.2 且 ROM >= 6.0.2,版本要求比较高。老项目如果 SDK 或 ROM 不满足,这个方法用不了。建议先用 has.canIUse('getRealNameStatus') 判断,再决定是否调用。若查到未实名,可以引导用户进入实名流程,例如调用 has.startRealNameAuth,成功后会返回 authId。
- has.getRealNameStatus({
- success: (res) => {
- console.info('实名状态:', res.status);
- // status: 实名状态值
- },
- fail: (err) => {
- console.error('查询失败:', err);
- }
- });
复制代码- if (res.status === 'verified') {
- console.info('已实名');
- } else {
- has.startRealNameAuth({
- success: (authId) => {
- console.info('实名授权成功:', authId);
- }
- });
- }
复制代码
另外,has.getServiceInfo 可获取元服务信息,返回 appId、appName、icon 等。它起始版本 1.0.19,依赖 SDK >= 6.0.0 且 ROM >= 6.0.0。对需要展示元服务基础信息的页面,可以先通过这个方法读取。
常见踩坑点
第一个坑是把 getUserInfo 和 getUserProfile 搞混。前者返回 code,要服务端换信息;后者直接返回昵称头像。只是展示用 getUserProfile,需要服务端存储用 getUserInfo。
第二个坑是以为 getPhoneNumber 会直接返回手机号。实际返回 code,必须由自己的服务器去华为接口换手机号,前端不要猜格式。
第三个坑是漏配 privacyApi。getUserInfo 和 getPhoneNumber 都要在 openHarmony/app.json5 里开启对应开关。不配置时 API 不注册,调用常见报错是 is not a function。
第四个坑是忽略版本要求。getRealNameStatus 需要 ASCF 1.0.20 + HarmonyOS SDK >= 6.0.2,getUserProfile 需要 SDK >= 6.0.0,getServiceInfo 需要 SDK >= 6.0.0。上线前最好用 canIUse 做能力判断。
第五个坑是忽略手机号 code 时效,以及隐私协议弹窗。用户还没同意隐私协议时,调用这些 API 可能先弹出隐私协议弹窗,同意后才能继续,这是 HarmonyOS 的合规要求。
统一封装 code 类隐私 API
getUserInfo 和 getPhoneNumber 结构相似,都是返回 code 后交给服务端,可以统一封装成 Promise,减少重复回调代码。封装时可以先 canIUse 判断,避免因配置缺失或版本不支持直接报错。
- function getPrivacyCode(apiName) {
- return new Promise((resolve, reject) => {
- if (!has.canIUse(apiName)) {
- reject(new Error(`${apiName} 不可用,请检查 privacyApi 配置`));
- return;
- }
- has[apiName]({
- success: (res) => resolve(res.code),
- fail: (err) => reject(err)
- });
- });
- }
- async function loginWithPhone() {
- try {
- const code = await getPrivacyCode('getPhoneNumber');
- const serverRes = await sendToServer('/api/login', { code });
- return serverRes;
- } catch (err) {
- console.error('手机号登录失败:', err.message);
- }
- }
- async function fetchUserProfile() {
- try {
- const code = await getPrivacyCode('getUserInfo');
- const serverRes = await sendToServer('/api/userInfo', { code });
- return serverRes;
- } catch (err) {
- console.error('获取用户信息失败:', err.message);
- }
- }
复制代码
业务流转与落地建议
以手机号登录为例,完整业务流是:- 用户点击“手机号登录”
- ↓
- 前端调 has.getPhoneNumber
- ↓
- 返回 code
- ↓
- 前端把 code 发给自己的服务器
- ↓
- 服务器用 code 调华为接口获取手机号
- ↓
- 服务器返回登录结果给前端
- ↓
- 前端保存登录态,跳转首页
复制代码
实际落地时,建议把隐私 API 调用集中在登录或用户信息模块,统一处理 canIUse、privacyApi 配置检查、code 上传和服务端返回。项目里的 getUserInfo Demo 已经注册到“开放能力”分类下,可以直接体验;getPhoneNumber 的示例代码需要配合服务端才能跑通。总体看,ASCF 隐私相关 API 数量不多,但配置容易漏,版本和前端/服务端边界要提前理清。 |