WeChatLoginBridge.ets 3.73 KB
import Want from '@ohos.app.ability.Want';
import common from '@ohos.app.ability.common';
import {
  BaseReq,
  BaseResp,
  ErrCode,
  SendAuthReq,
  SendAuthResp,
  WXAPIFactory,
  WXApi,
  WXApiEventHandler,
} from '@tencent/wechat_open_sdk';
import { FlutterError, Result, WeChatHostApi } from '../pigeon/WeChatApi';

/**
 * Fill in the AppID created for the HarmonyOS application in WeChat Open
 * Platform. Keep AppSecret on the server only.
 */
const WECHAT_APP_ID = 'wx42b603acf3dd68f5';

/** Bridges the native OpenSDK authorization callback to Flutter. */
export class WeChatLoginBridge extends WeChatHostApi implements WXApiEventHandler {
  private readonly context: common.UIAbilityContext;
  private readonly wxApi: WXApi;
  private pendingResult: Result<string> | null = null;

  constructor(context: common.UIAbilityContext) {
    super();
    this.context = context;
    this.wxApi = WXAPIFactory.createWXAPI(WECHAT_APP_ID, context);
  }

  requestAuthorizationCode(result: Result<string>): void {
    if (WECHAT_APP_ID.length === 0) {
      result.error(new FlutterError(
        'wechat_app_id_missing',
        'Set WECHAT_APP_ID in WeChatLoginBridge.ets first.',
        'WeChatError',
      ));
      return;
    }
    if (this.pendingResult !== null) {
      result.error(new FlutterError(
        'wechat_authorization_in_progress',
        '微信授权进行中',
        'WeChatError',
      ));
      return;
    }
    if (!this.wxApi.isWXAppInstalled()) {
      result.error(new FlutterError(
        'wechat_not_installed',
        '微信未安装',
        'WeChatError',
      ));
      return;
    }

    const request = new SendAuthReq();
    request.scope = 'snsapi_userinfo';
    request.state = 'none';
    request.callbackAbility = 'EntryAbility';
    this.pendingResult = result;

    try {
      const sent = this.wxApi.sendReq(this.context, request);
      if (sent instanceof Promise) {
        sent.then((success) => this.onRequestSent(success)).catch((error: Error) => {
          this.finishWithError('wechat_request_failed', error.message);
        });
      } else {
        this.onRequestSent(sent);
      }
    } catch (error) {
      this.finishWithError('wechat_request_failed', (error as Error).message);
    }
  }

  handleWant(want: Want): void {
    this.wxApi.handleWant(want, this);
  }

  /**
   * WeChat does not send an authorization response when the user simply
   * returns to our app. Complete the pending Pigeon call in that case, so the
   * Flutter loading overlay is always dismissed.
   */
  cancelPendingAuthorization(): void {
    if (this.pendingResult === null) {
      return;
    }
    this.finishWithError(
      'wechat_authorization_cancelled',
      '微信授权已取消',
    );
  }

  onReq(_request: BaseReq): void {}

  onResp(response: BaseResp): void {
    if (!(response instanceof SendAuthResp)) {
      return;
    }
    if (response.errCode === ErrCode.ERR_OK && response.code?.length) {
      this.finishWithCode(response.code);
      return;
    }
    this.finishWithError(
      'wechat_authorization_failed',
      response.errStr ?? `WeChat authorization failed with error ${response.errCode}.`,
    );
  }

  private onRequestSent(success: boolean): void {
    if (!success) {
      this.finishWithError('wechat_request_failed', 'Unable to open WeChat.');
    }
  }

  private finishWithCode(code: string | undefined): void {
    const result = this.pendingResult;
    this.pendingResult = null;
    if (result !== null && code !== undefined) {
      result.success(code);
    }
  }

  private finishWithError(code: string, message: string): void {
    const result = this.pendingResult;
    this.pendingResult = null;
    if (result !== null) {
      result.error(new FlutterError(code, message, 'WeChatError'));
    }
  }
}