HuaweiAuth.ets 6.07 KB
import { authentication, extendService } from '@kit.AccountKit';
import { AccountManagerUtils, EmitterEventId, EmitterUtils, Logger } from 'wdKit/Index';
import { util } from '@kit.ArkTS';
import { DEFAULT } from '@ohos/hypium';
import { BusinessError } from '@kit.BasicServicesKit';

const TAG = "HuaweiOneKeyAuth"

export default class HuaweiAuth {

  // 是否开启
  static enable = true
  // 匿名手机号
  private _anonymousPhone?: string
  get anonymousPhone() {
    return this._anonymousPhone
  }

  private static instance: HuaweiAuth
  static sharedInstance(): HuaweiAuth {
    if (!HuaweiAuth.instance) {
      HuaweiAuth.instance = new HuaweiAuth()
    }
    return HuaweiAuth.instance
  }

  registerEvents() {
    // 注册用户退出登录,取一次用来下次使用
    EmitterUtils.receiveEvent(EmitterEventId.FORCE_USER_LOGIN_OUT, ((str?: string) => {
      HuaweiAuth.sharedInstance().rePrefetchAnonymousPhone()
    }))
    EmitterUtils.receiveEvent(EmitterEventId.APP_ENTER_FOREGROUD, ((str?: string) => {
      AccountManagerUtils.isLogin().then((login) => {
        if (!login) {
          HuaweiAuth.sharedInstance().rePrefetchAnonymousPhone()
        }
      })
    }))
  }

  // 重新预取手机号(App启动未登录、回前台未登录、和退出登录 时调用提前取号)
  rePrefetchAnonymousPhone() {
    this._anonymousPhone = undefined
    this.fetchAnonymousPhone()
  }

  // 要登录时,先调用。如果获取到手机号了 则弹起一键登录页面
  fetchAnonymousPhone() : Promise<string> {

    return new Promise((resolve, fail) => {
      if (this.anonymousPhone) {
        resolve(this.anonymousPhone)
        return
      }

      let authRequest = new authentication.HuaweiIDProvider().createAuthorizationWithHuaweiIDRequest();
      // 权限有 phone 、email、realTimePhone、quickLoginMobilePhone,这里用获取匿名手机号
      authRequest.scopes = ['quickLoginAnonymousPhone'];
      authRequest.state = util.generateRandomUUID();
      authRequest.forceAuthorization = false;
      let controller = new authentication.AuthenticationController(getContext(this));
      try {
        controller.executeRequest(authRequest).then((response: authentication.AuthorizationWithHuaweiIDResponse) => {
          let anonymousPhone = response.data?.extraInfo?.quickLoginAnonymousPhone;
          if (anonymousPhone) {
            Logger.infoOptimize(TAG, () => {
              return 'get anonymousPhone, ' + JSON.stringify(response)
            })
            this._anonymousPhone = anonymousPhone as string
            resolve(this._anonymousPhone)
            return;
          }

          Logger.info(TAG, 'get anonymousPhone is empty. ' + JSON.stringify(response));
          fail("获取匿名手机号为空")
        }).catch((err: BusinessError) => {
          Logger.error(TAG, 'get anonymousPhone failed. ' + JSON.stringify(err));
          fail("获取匿名手机号失败")
        })
      } catch (err) {
        Logger.error(TAG, 'get anonymousPhone fail. ' + JSON.stringify(err));
        fail("获取匿名手机号失败")
      }
    })
  }

  // 华为账号获取orofile信息
  requestProfile() : Promise<WDHuaweiProfileData> {

    // let loginRequest = new authentication.HuaweiIDProvider().createLoginWithHuaweiIDRequest();
    // // 当用户未登录华为帐号时,是否强制拉起华为帐号登录界面
    // loginRequest.forceLogin = true;
    // loginRequest.state = util.generateRandomUUID();

    // 创建授权请求,并设置参数
    let loginRequest = new authentication.HuaweiIDProvider().createAuthorizationWithHuaweiIDRequest();
    // 获取头像昵称需要传如下scope
    loginRequest.scopes = ['profile'];
    // 若开发者需要进行服务端开发,则需传如下permission获取authorizationCode
    loginRequest.permissions = ['serviceauthcode'];
    // 用户是否需要登录授权,该值为true且用户未登录或未授权时,会拉起用户登录或授权页面
    loginRequest.forceAuthorization = true;
    loginRequest.state = util.generateRandomUUID();

    return new Promise((resolve, fail) => {

      try {
        let controller = new authentication.AuthenticationController(getContext(this));
        controller.executeRequest(loginRequest, (err, data) => {
          if (err) {
            Logger.error(TAG, 'requestProfile fail, ' + JSON.stringify(err))
            fail(err)
            return;
          }
          let loginWithHuaweiIDResponse = data as authentication.AuthorizationWithHuaweiIDResponse;
          let state = loginWithHuaweiIDResponse.state;
          if (state != undefined && loginRequest.state != state) {
            Logger.error(TAG, 'requestProfile fail, The state is different' + JSON.stringify(loginWithHuaweiIDResponse))
            fail({
              code: 99999,
              name: "一键登录获取用户信息失败",
              message:"状态错误:" + `请求状态 ${loginRequest.state}, 结果状态 ${state}`
            } as BusinessError)
            return;
          }

          Logger.info(TAG, 'requestProfile success, ' + JSON.stringify(loginWithHuaweiIDResponse));
          let authorizationCode = loginWithHuaweiIDResponse.data?.authorizationCode;
          let nickName = loginWithHuaweiIDResponse.data?.nickName
          let avatarUri = loginWithHuaweiIDResponse.data?.avatarUri

          resolve({avatarUri: avatarUri, nickName: nickName } as WDHuaweiProfileData)
        });
      } catch (error) {
        Logger.error(TAG, 'requestProfile fail, ' +  JSON.stringify(error))
        fail(error)
      }
    });
  }

  // 打开账户中心
  openAccountCenter() {
    try {
      extendService.startAccountCenter(getContext(this), (err, data) => {
        if (err) {
          Logger.info(TAG, 'startAccountCenterWithCallback fail,error: ' + JSON.stringify(err));
          return;
        }
        Logger.info(TAG, 'startAccountCenterWithCallback success');
      });
    } catch (error) {
      Logger.error(TAG, 'startAccountCenterWithCallback fail,error: ' + JSON.stringify(error));
    }
  }
}

export interface WDHuaweiProfileData {
  avatarUri?: string
  nickName?: string
}