版本记录
SDK说明
本文档用于指导游戏应用接入鸿蒙 bstsdk。当前SDK版本为 4.8.0.5-harmony,HAR 包版本为 1.0.1,兼容目标为 OpenHarmony API 10,主要提供初始化、登录、登出、角色上报、支付、客服、悬浮球用户中心及退出应用等能力。
bstsdk
4.8.0.5-harmony
1.0.1
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 显示,无需系统悬浮球权限。
entry/libs/bstsdk.har
ohpm install --all
添加 SDK 依赖
在应用 entry/oh-package.json5 中添加本地 HAR 依赖:
entry/oh-package.json5
{ "dependencies": { "bstsdk": "file:./libs/bstsdk.har" } }
如 SDK 以远程包方式提供,请按实际包名和版本替换依赖来源。
配置网络权限
在应用 entry/src/main/module.json5 中声明网络权限:
entry/src/main/module.json5
{ "module": { "requestPermissions": [ { "name": "ohos.permission.INTERNET" }, { "name": "ohos.permission.GET_NETWORK_INFO" } ] } }
悬浮球由 SdkHost 内的页面组件显示,无需系统悬浮球权限。
SdkHost
添加 SDK 配置文件
将配置文件放至以下路径:
entry/src/main/resources/rawfile/bstConfig.json
bstConfig.json 示例:
bstConfig.json
{ "appId": "替换为平台分配的 appId", "domain": "替换为平台分配的 domain", "alliance": "", "promotionId": "" }
字段说明:
生命周期转发
在应用 UIAbility 中转发生命周期。SDK 使用 UIAbilityContext 和 WindowStage 接收宿主上下文与生命周期,由页面中的 SdkHost 承载登录页、支付页、悬浮球和隐私弹窗。
UIAbility
UIAbilityContext
WindowStage
隐私确认前不要调用 SDK 的 onAppCreate()。先绑定 WindowStage 并加载宿主页,用户同意后调用 init(),由 SDK 自动完成 onAppCreate()。
onAppCreate()
init()
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(); } }
初始化说明
应用页面获取到 UIAbilityContext 后,先显示隐私弹窗。用户同意后调用 init(),收到 sdk_init_success() 后,才可调用登录、支付和角色上报接口。
sdk_init_success()
隐私弹窗接口
showPrivacyDialog(context):显示 SDK 隐私确认弹窗,用户可查看用户协议和隐私政策,并选择同意或拒绝。
showPrivacyDialog(context)
const accepted = await sdk.showPrivacyDialog(context);
showPrivacyDialog(context, privacyUrl, agreementUrl):使用传入的隐私政策地址和用户协议地址显示隐私确认弹窗。
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 初始化接口。
Promise<boolean>
true
false
初始化示例
在根页面挂载一次 SdkHost,在其 onReady 回调中开始隐私确认。下面的完整页面示例在同意后初始化 SDK,并转发返回键事件:协议详情返回隐私弹窗,主弹窗等待用户明确同意或拒绝。点击遮罩不会关闭弹窗。
onReady
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%'); } }
初始化回调
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 交付。
bst-api10-bootstrap.js
BstConfig.API10_H5_BOOTSTRAP_ENABLED = true
登录
初始化成功后调用以下接口打开登录页:
BstSDKManager.getInstance().SdkShowLogin();
登录成功回调:
sdk_login_success(userId: string): void { // 保存 SDK 用户 ID }
登录失败回调:
sdk_login_fail(code: number, reason: string): void { // 根据错误码和原因提示用户 }
登录成功后,SDK 会自动关闭登录页,并按服务端配置显示悬浮球。
登出
BstSDKManager.getInstance().SdkLogout();
登出成功回调:
sdk_logout(): void { // 清理应用本地登录态和角色数据 }
上报接口
BstSDKManager.getInstance().SdkUploadGameRoleInfo(roleData);
角色数据示例
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));
上报事件说明
建议在创建角色、进入游戏、升级和支付前等关键节点上报角色信息。
支付接口
BstSDKManager.getInstance().SdkShowRecharge(roleData, orderInfo, timestamp, sign);
接口参数
OrderInfo 字段说明
支付调用示例
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 平台分配的支付密钥和签名规则生成。
支付结果回调
sdk_recharge_success(json: string): void { // 支付成功。建议以服务端发货通知或主动查单结果为最终发货依据。 } sdk_recharge_fail(code: number, reason: string): void { // 支付失败或取消 }
注意事项
◆ cpOrderID 必须唯一,不能复用;
cpOrderID
◆ 支付前必须完成登录;
◆ timestamp 和 sign 不能为空,否则 SDK 会直接回调支付失败;
timestamp
sign
◆ 支付页由 SDK 内部展示。支付期间会隐藏悬浮球,支付页关闭后登录态有效时会恢复悬浮球。
悬浮球行为
登录成功后,SDK 会根据初始化接口返回的配置显示悬浮球。应用一般不需要直接控制悬浮球。
退出接口
在退出按钮或返回键逻辑中调用:
BstSDKManager.getInstance().exitApp();
退出处理说明
◆ 用户点击“是”:SDK 先回调应用 exit_app(),再由 SDK 内部结束当前 Ability;
exit_app()
◆ 用户点击“否”:取消退出,SDK 会恢复悬浮球显示。
exit_app(): void { // SDK 已确认退出。应用可在此保存进度、打点或清理临时状态。 // 不需要再次主动退出应用,SDK 内部会执行退出。 }
回调方法
应用需要实现 GCallback:
GCallback
最小实现示例
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 {} }
应用启动,隐私确认前不调用 SDK 的 onAppCreate()。
在 UIAbility.onWindowStageCreate() 中调用 SDK 的 onWindowStageCreate(windowStage),然后加载宿主页。
UIAbility.onWindowStageCreate()
onWindowStageCreate(windowStage)
根页面挂载 SdkHost 后,在 onReady 中获取 UIAbilityContext 并调用 showPrivacyDialog(context),或显式传入隐私政策和用户协议地址。
等待隐私接口返回 true 后调用 init(context, callback);拒绝或发生异常时不继续初始化。
init(context, callback)
收到 sdk_init_success() 后开放登录入口。
用户点击登录时调用 SdkShowLogin()。
SdkShowLogin()
收到 sdk_login_success(userId) 后保存登录态。
sdk_login_success(userId)
创建角色、进入游戏、升级等节点调用 SdkUploadGameRoleInfo()。
SdkUploadGameRoleInfo()
用户支付时生成唯一订单号、时间戳和签名,调用 SdkShowRecharge()。
SdkShowRecharge()
收到支付回调后展示结果,并以服务端通知或查单结果作为最终发货依据。
用户登出时调用 SdkLogout()。
SdkLogout()
用户退出游戏时调用 exitApp()。
exitApp()
构建 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 打包时以应用权限声明为准。
ohos.permission.INTERNET
初始化失败
◆ 确认 rawfile 下存在 bstConfig.json;
rawfile
◆ 确认 bstConfig.json 中的 appId、domain 正确;
appId
domain
◆ 确认设备网络可访问 SDK 服务域名;
◆ 确认应用已声明 ohos.permission.INTERNET。
登录或支付页面没有显示
◆ 确认已在 onWindowStageCreate() 调用 BstSDKManager.getInstance().onWindowStageCreate(windowStage);
onWindowStageCreate()
BstSDKManager.getInstance().onWindowStageCreate(windowStage)
◆ 确认初始化成功后再调用登录或支付;
◆ 确认当前页面能获取到 UIAbilityContext。
支付失败
◆ 确认 cpOrderID 唯一且非空;
◆ 确认 timestamp 为秒级时间戳字符串;
◆ 确认 sign 按平台规则生成;
◆ 确认 OrderInfo.amount、goodsID、goodsName 正确,且当前已登录并具有完整角色信息。
OrderInfo.amount
goodsID
goodsName
点击退出框“否”后悬浮球没有显示
用户点击“否”后,如 SDK 仍处于登录状态,会自动调用悬浮球显示逻辑。若仍未显示,请检查初始化接口是否配置隐藏悬浮球,或当前是否仍有 SDK 登录页、支付页在显示。
示例文件
entry/src/main/ets/entryability/EntryAbility.ets entry/src/main/ets/pages/Index.ets
建议接入方优先参考 Demo 中的生命周期转发、初始化、回调实现和支付调用方式。