鸿蒙游戏对接文档

一、版本记录

  1. 版本记录

    版本号修改记录
    1.0.0鸿蒙 BSTSDK 接入文档
    1.0.1新增隐私确认弹窗和自定义协议地址接口;调整为用户同意后初始化 SDK;适配 OpenHarmony API 10,增加 SdkHost 页面容器。

二、概述

  1. SDK说明

    本文档用于指导游戏应用接入鸿蒙 bstsdk。当前SDK版本为 4.8.0.5-harmony,HAR 包版本为 1.0.1,兼容目标为 OpenHarmony API 10,主要提供初始化、登录、登出、角色上报、支付、客服、悬浮球用户中心及退出应用等能力。

  2. SDK引用

    SDK 对外入口:

    import { BstSDKManager } from 'bstsdk';

           

    常用数据类型:

    import { BstSDKManager, GCallback, GameRoleData, GameRoleEvent, OrderInfo } from 'bstsdk';

       

三、工程接入

将 HAR 放入 entry/libs/bstsdk.har,执行 ohpm install --all。宿主工程的 compileSdkVersion、compatibleSdkVersion、targetSdkVersion 均设为 10,runtimeOS 设为 OpenHarmony,useNormalizedOHMUrl 设为 false。声明 INTERNET、GET_NETWORK_INFO 权限;悬浮球由 SdkHost 显示,无需系统悬浮球权限。

  1. 添加 SDK 依赖

    在应用 entry/oh-package.json5 中添加本地 HAR 依赖:

    {
    
      "dependencies": {
    
        "bstsdk": "file:./libs/bstsdk.har"
    
      }
    
    }

           

    如 SDK 以远程包方式提供,请按实际包名和版本替换依赖来源。

  2. 配置网络权限

    在应用 entry/src/main/module.json5 中声明网络权限:

    {
    
      "module": {
    
        "requestPermissions": [
    
          {
    
            "name": "ohos.permission.INTERNET"
    
          },
          {
            "name": "ohos.permission.GET_NETWORK_INFO"
          }
    
        ]
    
      }
    
    }

           

    悬浮球由 SdkHost 内的页面组件显示,无需系统悬浮球权限。

  3. 添加 SDK 配置文件

    将配置文件放至以下路径:

    entry/src/main/resources/rawfile/bstConfig.json

           

    bstConfig.json 示例:

    {
    
      "appId": "替换为平台分配的 appId",
    
      "domain": "替换为平台分配的 domain",
    
      "alliance": "",
    
      "promotionId": ""
    
    }

           

    字段说明:

    文件字段说明
    bstConfig.jsonappIdBST 平台分配的应用 ID
    bstConfig.jsondomainSDK 服务域名
    bstConfig.jsonalliance联盟参数;没有则留空
    bstConfig.jsonpromotionId推广 ID;没有则留空

四、Ability 生命周期接入

  1. 生命周期转发

    在应用 UIAbility 中转发生命周期。SDK 使用 UIAbilityContext 和 WindowStage 接收宿主上下文与生命周期,由页面中的 SdkHost 承载登录页、支付页、悬浮球和隐私弹窗。

    隐私确认前不要调用 SDK 的 onAppCreate()。先绑定 WindowStage 并加载宿主页,用户同意后调用 init(),由 SDK 自动完成 onAppCreate()。

    import UIAbility from '@ohos.app.ability.UIAbility';
    import window from '@ohos.window';
    import { BstSDKManager } from 'bstsdk';
    
    export default class EntryAbility extends UIAbility {
      onWindowStageCreate(windowStage: window.WindowStage): void {
        BstSDKManager.getInstance().onWindowStageCreate(windowStage);
        windowStage.loadContent('pages/Index');
      }
    
      onWindowStageDestroy(): void {
        BstSDKManager.getInstance().onWindowStageDestroy();
      }
    
      onForeground(): void {
        BstSDKManager.getInstance().onForeground();
      }
    
      onBackground(): void {
        BstSDKManager.getInstance().onBackground();
      }
    }

五、SDK 初始化

  1. 初始化说明

    应用页面获取到 UIAbilityContext 后,先显示隐私弹窗。用户同意后调用 init(),收到 sdk_init_success() 后,才可调用登录、支付和角色上报接口。

  2. 隐私弹窗接口

    showPrivacyDialog(context):显示 SDK 隐私确认弹窗,用户可查看用户协议和隐私政策,并选择同意或拒绝。

    const accepted = await sdk.showPrivacyDialog(context);

    showPrivacyDialog(context, privacyUrl, agreementUrl):使用传入的隐私政策地址和用户协议地址显示隐私确认弹窗。

    const accepted = await sdk.showPrivacyDialog(
      context,
      'https://www.example.com/wap/article/privacy.aspx',
      'https://www.example.com/wap/article/agreement.aspx'
    );

    两个接口均返回 Promise<boolean>:true 表示用户同意,false 表示拒绝或宿主窗口销毁。用户同意后再调用 SDK 初始化接口。

  3. 初始化示例

    在根页面挂载一次 SdkHost,在其 onReady 回调中开始隐私确认。下面的完整页面示例在同意后初始化 SDK,并转发返回键事件:协议详情返回隐私弹窗,主弹窗等待用户明确同意或拒绝。点击遮罩不会关闭弹窗。

    import common from '@ohos.app.ability.common';
    import { SdkHost, BstSDKManager, GCallback } from 'bstsdk';
    
    @Entry
    @Component
    struct Index {
      private readonly sdk: BstSDKManager = BstSDKManager.getInstance();
      private callback?: GCallback;
    
      private initializeSdk(): void {
        const context = getContext(this) as common.UIAbilityContext;
        this.callback = new DemoSdkCallback();
        void this.initializeWithPrivacy(context, this.callback);
      }
    
      onBackPress(): boolean {
        return this.sdk.onPrivacyBackPressed();
      }
    
      private async initializeWithPrivacy(context: common.UIAbilityContext, callback: GCallback): Promise<void> {
        try {
          const accepted = await this.sdk.showPrivacyDialog(
            context,
            'https://www.example.com/wap/article/privacy.aspx',
            'https://www.example.com/wap/article/agreement.aspx'
          );
          if (!accepted) {
            await context.terminateSelf();
            return;
          }
          await this.sdk.init(context, callback);
        } catch (error) {
          console.error('SDK 启动失败:' + (error as Error).message);
        }
      }
    
      build() {
        Stack() {
          SdkHost({ onReady: () => this.initializeSdk() }) {
            Column() {
              Text('游戏主页');
            }.width('100%').height('100%');
          }
        }.width('100%').height('100%');
      }
    }
  4. 初始化回调

    class DemoSdkCallback implements GCallback {
      sdk_init_success(): void {
        // SDK 初始化成功,可以开放登录按钮
      }
    
      sdk_init_fail(code?: number, reason?: string): void {
        // SDK 初始化失败,建议提示用户或重试
      }
    
      sdk_login_success(userId: string): void {}
      sdk_login_fail(code: number, reason: string): void {}
      sdk_logout(): void {}
      sdk_recharge_success(json: string): void {}
      sdk_recharge_fail(code: number, reason: string): void {}
      exit_app(): void {}
    }

六、登录与登出

服务端启用 TCP 登录限制时,API 10 的 H5 需在所有业务脚本前同步加载 bst-api10-bootstrap.js。确认部署后,在调用登录前设置 BstConfig.API10_H5_BOOTSTRAP_ENABLED = true(从 bstsdk 导入 BstConfig)。未确认部署时登录返回错误 -8。该脚本随 HAR 交付。

  1. 登录

    初始化成功后调用以下接口打开登录页:

    BstSDKManager.getInstance().SdkShowLogin();

           

    登录成功回调:

    sdk_login_success(userId: string): void {
    
      // 保存 SDK 用户 ID
    
    }

           

    登录失败回调:

    sdk_login_fail(code: number, reason: string): void {
    
      // 根据错误码和原因提示用户
    
    }

           

    登录成功后,SDK 会自动关闭登录页,并按服务端配置显示悬浮球。

  2. 登出

    BstSDKManager.getInstance().SdkLogout();

           

    登出成功回调:

    sdk_logout(): void {
    
      // 清理应用本地登录态和角色数据
    
    }

       

七、角色上报

  1. 上报接口

    BstSDKManager.getInstance().SdkUploadGameRoleInfo(roleData);

       

  2. 角色数据示例

    import { GameRoleData, GameRoleEvent } from 'bstsdk';
    
    
    
    function createRoleData(eventName: string): GameRoleData {
    
      const roleData = new GameRoleData();
    
      roleData.serverId = '1';
    
      roleData.serverName = 'Server 1';
    
      roleData.roleId = '10000';
    
      roleData.roleName = 'Demo Player';
    
      roleData.roleLevel = '1';
    
      roleData.roleBalance = '0';
    
      roleData.vipLevel = '0';
    
      roleData.partyId = '';
    
      roleData.partyName = '';
    
      roleData.roleGender = '';
    
      roleData.rolePower = '0';
    
      roleData.partyRoleId = '';
    
      roleData.partyRoleName = '';
    
      roleData.professionId = '';
    
      roleData.profession = '';
    
      roleData.friendList = '[]';
    
      roleData.eventName = eventName;
    
      return roleData;
    
    }
    
    
    
    BstSDKManager.getInstance().SdkUploadGameRoleInfo(createRoleData(GameRoleEvent.create));

       

  3. 上报事件说明

    常量值使用场景
    GameRoleEvent.online1角色上线
    GameRoleEvent.create2创建角色
    GameRoleEvent.upleve3角色升级
    GameRoleEvent.pay4支付前角色信息
    GameRoleEvent.offline5角色离线
    GameRoleEvent.exit99退出游戏

    建议在创建角色、进入游戏、升级和支付前等关键节点上报角色信息。

八、支付接入

  1. 支付接口

    BstSDKManager.getInstance().SdkShowRecharge(roleData, orderInfo, timestamp, sign);

       

  2. 接口参数

    参数名称类型说明
    roleDataGameRoleData当前支付角色信息,建议 eventName 使用 GameRoleEvent.pay
    orderInfoOrderInfo应用订单和商品信息
    timestampstring秒级时间戳
    signstring应用按平台规则生成的签名
  3. OrderInfo 字段说明

    字段类型说明
    goodsIDstring商品 ID
    goodsNamestring商品名称
    cpOrderIDstringCP 订单号,必须唯一
    countnumber商品数量
    amountnumber支付金额,单位按平台约定
    goodsDescstring商品描述
    extrasParamsstringCP 透传参数,建议传 JSON 字符串,例如 [] 或 {}
  4. 支付调用示例

    import { BstSDKManager, GameRoleEvent, OrderInfo } from 'bstsdk';
    
    
    
    async function pay(): Promise<void> {
    
      const roleData = createRoleData(GameRoleEvent.pay);
    
    
    
      const orderInfo = new OrderInfo();
    
      orderInfo.cpOrderID = `CP${Date.now()}`;
    
      orderInfo.amount = 1;
    
      orderInfo.count = 100;
    
      orderInfo.goodsID = 'goods_001';
    
      orderInfo.goodsName = 'Coins';
    
      orderInfo.goodsDesc = 'Demo package';
    
      orderInfo.extrasParams = '[]';
    
    
    
      const timestamp = Math.floor(Date.now() / 1000).toString();
    
      const sign = await createPaySign(orderInfo, timestamp);
    
    
    
      BstSDKManager.getInstance().SdkShowRecharge(roleData, orderInfo, timestamp, sign);
    
    }

           

    sign 由应用按 BST 平台分配的支付密钥和签名规则生成。

  5. 支付结果回调

    sdk_recharge_success(json: string): void {
    
      // 支付成功。建议以服务端发货通知或主动查单结果为最终发货依据。
    
    }
    
    
    
    sdk_recharge_fail(code: number, reason: string): void {
    
      // 支付失败或取消
    
    }

       

  6. 注意事项

    ◆ cpOrderID 必须唯一,不能复用;

    ◆ 支付前必须完成登录;

    ◆ timestamp 和 sign 不能为空,否则 SDK 会直接回调支付失败;

    ◆ 支付页由 SDK 内部展示。支付期间会隐藏悬浮球,支付页关闭后登录态有效时会恢复悬浮球。

九、客服与悬浮球

  1. 悬浮球行为

    登录成功后,SDK 会根据初始化接口返回的配置显示悬浮球。应用一般不需要直接控制悬浮球。

十、退出应用

  1. 退出接口

    在退出按钮或返回键逻辑中调用:

    BstSDKManager.getInstance().exitApp();

       

  2. 退出处理说明

    ◆ 用户点击“是”:SDK 先回调应用 exit_app(),再由 SDK 内部结束当前 Ability;

    ◆ 用户点击“否”:取消退出,SDK 会恢复悬浮球显示。

    exit_app(): void {
    
      // SDK 已确认退出。应用可在此保存进度、打点或清理临时状态。
    
      // 不需要再次主动退出应用,SDK 内部会执行退出。
    
    }

       

十一、完整回调说明

  1. 回调方法

    应用需要实现 GCallback:

    方法触发时机
    sdk_init_success()SDK 初始化成功
    sdk_init_fail(code?, reason?)SDK 初始化失败
    sdk_login_success(userId)登录成功,返回 SDK 用户 ID
    sdk_login_fail(code, reason)登录失败
    sdk_logout()登出成功
    sdk_recharge_success(json)支付成功
    sdk_recharge_fail(code, reason)支付失败或取消
    exit_app()SDK 确认退出应用前通知应用
  2. 最小实现示例

    import { GCallback } from 'bstsdk';
    
    
    
    class GameSdkCallback implements GCallback {
    
      sdk_init_success(): void {}
    
      sdk_init_fail(code?: number, reason?: string): void {}
    
      sdk_login_success(userId: string): void {}
    
      sdk_login_fail(code: number, reason: string): void {}
    
      sdk_logout(): void {}
    
      sdk_recharge_success(json: string): void {}
    
      sdk_recharge_fail(code: number, reason: string): void {}
    
      exit_app(): void {}
    
    }

       

十二、推荐调用流程

  1. 应用启动,隐私确认前不调用 SDK 的 onAppCreate()。

  2. 在 UIAbility.onWindowStageCreate() 中调用 SDK 的 onWindowStageCreate(windowStage),然后加载宿主页。

  3. 根页面挂载 SdkHost 后,在 onReady 中获取 UIAbilityContext 并调用 showPrivacyDialog(context),或显式传入隐私政策和用户协议地址。

  4. 等待隐私接口返回 true 后调用 init(context, callback);拒绝或发生异常时不继续初始化。

  5. 收到 sdk_init_success() 后开放登录入口。

  6. 用户点击登录时调用 SdkShowLogin()。

  7. 收到 sdk_login_success(userId) 后保存登录态。

  8. 创建角色、进入游戏、升级等节点调用 SdkUploadGameRoleInfo()。

  9. 用户支付时生成唯一订单号、时间戳和签名,调用 SdkShowRecharge()。

  10. 收到支付回调后展示结果,并以服务端通知或查单结果作为最终发货依据。

  11. 用户登出时调用 SdkLogout()。

  12. 用户退出游戏时调用 exitApp()。

十三、常见问题

  1. 构建 HAR 时提示 INTERNET 权限

    如日志出现以下内容:

    To use this API, you need to apply for the permissions: ohos.permission.INTERNET

           

    请确认应用 entry/src/main/module.json5 已声明 ohos.permission.INTERNET。HAR 单独编译时仍可能出现权限 warning,应用 App 打包时以应用权限声明为准。

  2. 初始化失败

    ◆ 确认 rawfile 下存在 bstConfig.json;

    ◆ 确认 bstConfig.json 中的 appId、domain 正确;

    ◆ 确认设备网络可访问 SDK 服务域名;

    ◆ 确认应用已声明 ohos.permission.INTERNET。

  3. 登录或支付页面没有显示

    ◆ 确认已在 onWindowStageCreate() 调用 BstSDKManager.getInstance().onWindowStageCreate(windowStage);

    ◆ 确认初始化成功后再调用登录或支付;

    ◆ 确认当前页面能获取到 UIAbilityContext。

  4. 支付失败

    ◆ 确认 cpOrderID 唯一且非空;

    ◆ 确认 timestamp 为秒级时间戳字符串;

    ◆ 确认 sign 按平台规则生成;

    ◆ 确认 OrderInfo.amount、goodsID、goodsName 正确,且当前已登录并具有完整角色信息。

  5. 点击退出框“否”后悬浮球没有显示

    用户点击“否”后,如 SDK 仍处于登录状态,会自动调用悬浮球显示逻辑。若仍未显示,请检查初始化接口是否配置隐藏悬浮球,或当前是否仍有 SDK 登录页、支付页在显示。

十四、Demo 参考

  1. 示例文件

    entry/src/main/ets/entryability/EntryAbility.ets
    
    entry/src/main/ets/pages/Index.ets

           

    建议接入方优先参考 Demo 中的生命周期转发、初始化、回调实现和支付调用方式。