facebook instant game 发布指南-API 参考文档 v6.0

FBInstant

小游戏 SDK 的顶级命名空间。


player

包含与当前玩家相关的功能和属性。


getID( )

玩家的唯一标识。Facebook 用户的玩家编号将保持不变,且仅限于特定游戏范围。这意味着同一个用户在不同的游戏中有不同的玩家编号。仅当 FBInstant.initializeAsync() 被解析后才应调用此函数。

示例

// This function should be called after FBInstant.initializeAsync()

// resolves.

var playerID = FBInstant.player.getID();

返回字符串玩家的唯一标识。


getSignedPlayerInfoAsync( )

获取玩家的唯一标识和签名,签名用于验证标识确实来自 Facebook,且没有被篡改。仅当 FBInstant.initializeAsync() 被解析后才应调用此函数。

参数

requestPayload字符串开发者指定的包含于已签名响应中的负载。

示例

// This function should be called after FBInstant.initializeAsync()

// resolves.

FBInstant.player.getSignedPlayerInfoAsync('my_metadata') 

    .then(function (result) {  

       // The verification of the ID and signature should happen on server side.        

       SendToMyServer(     

            result.getPlayerID(), // same value as FBInstant.player.getID()   

            result.getSignature(),    

           'GAIN_COINS',    

           100); 

});

抛出INVALID_PARAM

抛出NETWORK_FAILURE

抛出CLIENT_UNSUPPORTED_OPERATION

返回Promise<SignedPlayerInfo>#signedplayerinfo对象解析的 promise。


getName( )

经本地化显示的玩家姓名。仅当 FBInstant.startGameAsync() 被解析后才应调用此函数。

示例

// This function should be called after FBInstant.startGameAsync()

// resolves.

var playerName = FBInstant.player.getName();

返回字符串经本地化显示的玩家姓名。


getPhoto( )

玩家公开头像的网址。此照片始终为正方形,尺寸至少为 200x200 像素。在游戏中显示时,确切的尺寸可能会有所变化。建议始终在显示之前将图片调整为需要的尺寸。对应的值将始终为 null,直至 FBInstant.startGameAsync() 被解析。

警告:由于使用 CORS 机制,在游戏 Canvas 中使用这些照片会导致照片损坏,这有碍于提取 Canvas 数据。为防止出现这种情况,应将您使用的图片的 cross-origin 属性设置为“anonymous”。

示例

var playerImage = new Image();

playerImage.crossOrigin = 'anonymous';

// This function should be called after FBInstant.startGameAsync()

// resolves.

playerImage.src = FBInstant.player.getPhoto();

返回字符串玩家公开头像的网址。


getDataAsync( )

从指定的云存储中检索当前玩家的数据。

参数

keys数组<字符串>唯一键数组,数据检索将针对这些键展开。

示例

FBInstant.player

    .getDataAsync(['achievements', 'currentLife']) 

    .then(function(data) {   

        console.log('data is loaded');   

        var achievements = data['achievements'];   

        var currentLife = data['currentLife']; 

});

抛出INVALID_PARAM

抛出NETWORK_FAILURE

抛出CLIENT_UNSUPPORTED_OPERATION

返回Promise<对象>此 promise 将在获得包含下列信息的对象时被解析:输入数组中指定的每个键的当前键值对(如存在)。


setDataAsync( )

设置要保存到指定云存储的当前玩家的数据。对于每个独立玩家,游戏最多可存储 1MB 的数据。

参数

data对象此对象包含应该保存到云存储的一组键值对。对象必须仅包含可序列化的值 — 任何不可序列化的值都会导致整个修改被拒绝。

示例

FBInstant.player

   .setDataAsync({   

        achievements: ['medal1', 'medal2', 'medal3'],   

        currentLife: 300, 

    }) 

    .then(function() {   

        console.log('data is set'); 

});

抛出INVALID_PARAM

抛出NETWORK_FAILURE

抛出PENDING_REQUEST

抛出CLIENT_UNSUPPORTED_OPERATION

返回Promise此 promise 将在输入值设定时被解析。注意:promise 被解析并不一定意味着输入已被存储,而是这意味着相关数据有效并已安排要被存储。这还能保证设置的所有值现在可在 player.getDataAsync 中使用。


flushDataAsync( )

立即将玩家数据的任何更改刷新到指定的云存储中。此函数的调用成本较高,应主要用于需要立即存储并告知游戏的重要更改。非重要更改应依赖于开放平台在后台进行存储。注意:当此函数的结果待定时,player.setDataAsync 调用将被拒绝。

示例

FBInstant.player

  .setDataAsync({   

     achievements: ['medal1', 'medal2', 'medal3'],   

     currentLife: 300, 

   }) 

   .then(FBInstant.player.flushDataAsync) 

   .then(function() {   

       console.log('Data persisted to FB!'); 

});

抛出INVALID_PARAM

抛出NETWORK_FAILURE

抛出PENDING_REQUEST

抛出CLIENT_UNSUPPORTED_OPERATION

返回Promise此 promise 将在更改保存成功时被解析,在更改保存失败时被拒绝。


getStatsAsync( )

从指定云存储检索当前玩家的统计数据。

参数

keys数组<字符串>?唯一键数组(可选),针对这些键检索统计数据。如果调用函数时没有设置此参数,则会提取所有统计数据。

示例

FBInstant.player

  .getStatsAsync(['level', 'zombiesSlain']) 

  .then(function(stats)) {   

    console.log('stats are loaded');   

    var level = data['level'];   

    var zombiesSlain = data['zombiesSlain']; 

  });

抛出INVALID_PARAM

抛出NETWORK_FAILURE

抛出CLIENT_UNSUPPORTED_OPERATION

返回Promise<对象>此 promise 将在获得包含下列信息的对象时被解析:输入数组中指定的每个键的当前键值对(如存在)。


setStatsAsync( )

设置要保存到指定云存储的当前玩家的统计数据。

参数

stats对象此对象包含应作为统计数据保存到云存储的键值对,能以各种方式显示或使用这些数据以提高玩家参与度。对象必须仅包含数值,任何非数值会导致整个修改被拒绝。

示例

FBInstant.player

   .setStatsAsync({   

      level: 5,   

      zombiesSlain: 27, 

    }) 

    .then(function() {   

      console.log('data is set'); 

     });

抛出INVALID_PARAM

抛出NETWORK_FAILURE

抛出PENDING_REQUEST

抛出CLIENT_UNSUPPORTED_OPERATION

返回Promise此 promise 将在输入值设定时被解析。注意:promise 被解析并不一定意味着输入已被存储,而是这意味着相关数据经过验证并已安排要被存储。这还能保证设置的所有值现在可在 player.getStatsAsync 中使用。


incrementStatsAsync( )

保存到指定云存储的当前玩家的增量统计数据。

参数

increments对象此对象包含一组键值对,这些键值对表示云存储中每个统计数据的增量是多少。对象必须仅包含数值,任何非数值会导致整个修改被拒绝。

示例

FBInstant.player

     .incrementStatsAsync({   

       level: 1,   

       zombiesSlain: 17,   

       rank: -1, 

     })

     .then(function(stats)) {   

         console.log('increments have been made! New values');   

         var level = data['level'];   

         var zombiesSlain = data['zombiesSlain']; 

      });

抛出INVALID_PARAM

抛出NETWORK_FAILURE

抛出PENDING_REQUEST

抛出CLIENT_UNSUPPORTED_OPERATION

返回Promise<对象>此 promise 将在获得包含下列信息的对象时被解析:输入字典中指定的每个键的更新键值对。注意:解析 promise 并不一定意味着更改已被存储,而是意味着增量有效且已安排要被执行。这还能保证增加的所有值现在可在 player.getStatsAsync 中使用。


getConnectedPlayersAsync( )

提取 ConnectedPlayer 对象的数组,这些对象包含与当前玩家关联的玩家的信息。

示例

var connectedPlayers = FBInstant.player.getConnectedPlayersAsync() 

    .then(function(players) { 

      console.log(players.map(function(player) {     

          return {       

             id: player.getID(),       

             name: player.getName(),     

          }   

       }));  

     });

// [{id: '123456789', name: 'Paul Atreides'}, {id: '987654321', name: 'Duncan Idaho'}]

抛出NETWORK_FAILURE

抛出CLIENT_UNSUPPORTED_OPERATION

返回Promise<数组<ConnectedPlayer>>此 promise 将在获得关联玩家对象列表时被解析。注意:只有当 FBInstant.startGameAsync()被解析时,此 promise 才会解析。


context

包含与当前游戏环境相关的功能和属性。


getID( )

当前游戏环境的唯一标识。这表示玩游戏的特定环境(例如:特定的Messenger 对话或 Facebook 帖子)。如果用户在独立环境中玩游戏,则此标识将为 null。仅当FBInstant.startGameAsync 被解析后才应调用此函数。

示例

// This function should be called after FBInstant.startGameAsync()

// resolves.

var contextID = FBInstant.context.getID();

返回字符串当前游戏环境的唯一标识。


getType( )

当前游戏环境的类型。POST — 一个 Facebook 帖子。THREAD — 一个 Messenger 对话。GROUP — 一个 Facebook 小组。SOLO — 默认环境,玩家是唯一的参与者。

仅当 FBInstant.startGameAsync 被解析后才应调用此函数。

示例

// This function should be called after FBInstant.startGameAsync()

// resolves.

var contextType = FBInstant.context.getType();

返回("POST"|"THREAD"|"GROUP"|"SOLO")当前游戏环境的类型。


isSizeBetween( )

此函数用于确定加入当前游戏环境的玩家数量是否在给定的最小值和最大值之间(包括最小值和最大值)。仅当其中一个边界值为 null 时,才会根据另一个边界值进行检查。在特定的游戏会话中,此函数始终会返回某环境内发出的第一个调用的最初结果。后续调用(无论参数是什么)将返回原始查询的答案,除非游戏环境发生变化且查询结果被重置。

仅当 FBInstant.startGameAsync 被解析后才应调用此函数。

如果提供的一个或两个参数无效,我们没有适合当前游戏环境的玩家数量,或者 API 在 startGameAsync() 解析之前被调用,此参数都会为 null。

参数

minSize数字环境规模查询的最小边界值。

minSize数字环境规模查询的最大边界值。

maxSize数字

示例

console.log(FBInstant.context.isSizeBetween(3, 5)); (Context size = 4)

// {answer: true, minSize: 3, maxSize: 5}


console.log(FBInstant.context.isSizeBetween(5, 7)); (Context size = 4)

// {answer: false, minSize: 5, maxSize: 7}


console.log(FBInstant.context.isSizeBetween(2, 10)); (Context size = 3)

// {answer: true, minSize: 2, maxSize: 10}

console.log(FBInstant.context.isSizeBetween(4, 8)); (Still in same context)

// {answer: true, minSize: 2, maxSize: 10}


console.log(FBInstant.context.isSizeBetween(3, null)); (Context size = 4)

// {answer: true, minSize: 3, maxSize: null}


console.log(FBInstant.context.isSizeBetween(null, 3)); (Context size = 4)

// {answer: false, minSize: null, maxSize: 3}


console.log(FBInstant.context.isSizeBetween("test", 5)); (Context size = 4)

// null


console.log(FBInstant.context.isSizeBetween(0, 100)); (Context size = null)

// null

返回ContextSizeResponse


switchAsync( )

请求切换到指定环境。如果玩家没有进入该环境的权限,或玩家未向游戏提供进入该环境的权限,请求将被拒绝。promise 将在游戏切换到指定环境时被解析。

参数

id字符串目标环境的编号。

示例

console.log(FBInstant.context.getID());

// 1122334455

FBInstant.context

     .switchAsync('1234567890') 

     .then(function() {   

       console.log(FBInstant.context.getID());  

       // 1234567890 

      });

抛出INVALID_PARAM

抛出SAME_CONTEXT

抛出NETWORK_FAILURE

抛出USER_INPUT

抛出PENDING_REQUEST

抛出CLIENT_UNSUPPORTED_OPERATION

返回Promise此 promise 将在游戏切换到指定环境时被解析,在切换失败时被拒绝。


chooseAsync( )

为玩家打开一个环境选择对话框。如果玩家选择可用的环境,客户端将尝试切换到这个环境,并在成功时解析。而如果玩家退出菜单或客户端未能切换到新环境,此函数将被拒绝。

参数

options对象此对象用于指定应提供的环境选项。

options.filters数组<ContextFilter>?适用于环境推荐的一组筛选条件。

options.maxSize数字在理想情况下,推荐环境应有的最大玩家数量。

options.minSize数字在理想情况下,推荐环境应有的最小玩家数量。

示例

console.log(FBInstant.context.getID());

// 1122334455

FBInstant.context

     .chooseAsync() 

     .then(function() {   

       console.log(FBInstant.context.getID());   

        // 1234567890 

       });


console.log(FBInstant.context.getID());

// 1122334455

FBInstant.context

     .chooseAsync({   

        filters: ['NEW_CONTEXT_ONLY'],   

        minSize: 3, 

      }) 

      .then(function() {   

        console.log(FBInstant.context.getID());   

         // 1234567890 

       });

抛出INVALID_PARAM

抛出SAME_CONTEXT

抛出NETWORK_FAILURE

抛出USER_INPUT

抛出PENDING_REQUEST

抛出CLIENT_UNSUPPORTED_OPERATION

返回Promise此 promise 将在游戏切换到用户选择的环境时被解析。否则此 promise 将被拒绝(例如用户退出对话框)。


createAsync( )

尝试在指定玩家和当前玩家之间创建环境或切换环境。如果列出的玩家不是当前玩家的关联玩家,或玩家未提供进入新环境的权限,则返回的 promise 将被拒绝。当游戏切换到新环境时,promise 将被解析。

参数

playerID字符串玩家的编号

示例

console.log(FBInstant.context.getID());

// 1122334455

FBInstant.context

     .createAsync('12345678') 

     .then(function() {   

       console.log(FBInstant.context.getID());   

        // 5544332211 

      });

抛出INVALID_PARAM

抛出SAME_CONTEXT

抛出NETWORK_FAILURE

抛出USER_INPUT

抛出PENDING_REQUEST

抛出CLIENT_UNSUPPORTED_OPERATION

返回Promise此 promise 将在游戏切换到新环境时被解析,在切换失败时被拒绝。


getPlayersAsync( )

获取#contextplayer对象的数组,其中包含与当前环境相关的活跃玩家(在过去 90 天内玩过游戏的用户)的信息。这可能包含当前玩家。

示例

var contextPlayers = FBInstant.context.getPlayersAsync() 

    .then(function(players) {   

      console.log(players.map(function(player) {     

          return {       

             id: player.getID(),       

             name: player.getName(),     

         }   

      })); 

    });

// [{id: '123456789', name: 'Luke'}, {id: '987654321', name: 'Leia'}]

抛出NETWORK_FAILURE

抛出CLIENT_UNSUPPORTED_OPERATION

抛出INVALID_OPERATION

返回Promise<数组<ContextPlayer>>


支付

[封闭公测]包含与游戏商品的支付和购买相关的函数和属性。


getCatalogAsync( )

获取游戏的商品目录。

示例

FBInstant.payments.getCatalogAsync().then(function (catalog) { 

    console.log(catalog); // [{productID: '12345', ...}, ...]

});

抛出CLIENT_UNSUPPORTED_OPERATION

抛出PAYMENTS_NOT_INITIALIZED

抛出NETWORK_FAILURE

返回Promise<数组<商品>>登记到游戏的一组商品。


purchaseAsync( )

开始特定商品的购买流程。

参数

purchaseConfigPurchaseConfig该项购买的配置详情。

示例

FBInstant.payments.purchaseAsync({ 

     productID: '12345', 

     developerPayload: 'foobar',

}).then(function (purchase) { 

   console.log(purchase); 

   // {productID: '12345', purchaseToken: '54321', developerPayload: 'foobar', ...}

});

抛出CLIENT_UNSUPPORTED_OPERATION

抛出PAYMENTS_NOT_INITIALIZED

抛出INVALID_PARAM

抛出NETWORK_FAILURE

返回Promise<购买>此 promise 将在玩家成功购买商品时被解析,否则会被拒绝。


getPurchasesAsync( )

获取玩家未消费的所有购买商品。最佳做法是,游戏在客户端表明已准备好执行支付相关操作时,立即获取当前玩家的购买商品。游戏随后可处理和消费正在等待被消费的任何购买商品。

示例

FBInstant.payments.getPurchasesAsync().then(function (purchases) { 

    console.log(purchase); 

    // [{productID: '12345', ...}, ...]

});

抛出CLIENT_UNSUPPORTED_OPERATION

抛出PAYMENTS_NOT_INITIALIZED

抛出NETWORK_FAILURE

返回Promise<数组<购买>>玩家为游戏购买的一组商品。


consumePurchaseAsync( )

消费当前玩家拥有的特定购买商品。在为玩家配置商品效果之前,游戏应先请求消费已购买的商品。购买的商品成功消费后,游戏应立即向玩家呈现购买商品的效果。

参数

purchaseToken字符串应消费的购买商品的购买口令。

示例

FBInstant.payments.consumePurchaseAsync('54321').then(function () { 

     // Purchase successfully consumed! 

     // Game should now provision the product to the player

});

抛出CLIENT_UNSUPPORTED_OPERATION

抛出PAYMENTS_NOT_INITIALIZED

抛出INVALID_PARAM

抛出NETWORK_FAILURE

返回Promise此 promise 在成功消费已购买的商品时被解析。


onReady( )

设置一个回调,在支付操作可进行时触发。

参数

callback函数当支付可进行时执行的回调函数。

示例

FBInstant.payments.onReady(function () { 

    console.log('Payments Ready!')

});

返回void


getLocale( )

当前的语言设置。根据这一结果确定当前的游戏应本地化为哪种语言。在 FBInstant.startGameAsync() 被解析之前,对应的值将不准确。

示例

// This function should be called after FBInstant.startGameAsync()

// resolves.

var locale = FBInstant.getLocale(); // 'en_US'

返回字符串当前的语言设置。


getPlatform( )

当前运行游戏的平台。对应的值将始终为 null,直至 FBInstant.initializeAsync() 被解析。

示例

// This function should be called after FBInstant.initializeAsync()

// resolves.

var platform = FBInstant.getPlatform(); // 'IOS'

返回平台


getSDKVersion( )

表示此 SDK 版本的字符串。

示例

// This function should be called after FBInstant.initializeAsync()

// resolves.

var sdkVersion = FBInstant.getSDKVersion(); // '2.0'

返回字符串SDK 版本。


initializeAsync( )

初始化 SDK 库。应在调用其他任何 SDK 函数之前调用此函数。

示例

FBInstant.initializeAsync().then(function() { 

     // Many properties will be null until the initialization completes. 

     // This is a good place to fetch them: 

     var locale = FBInstant.getLocale(); // 'en_US' 

     var platform = FBInstant.getPlatform(); // 'IOS' 

     var sdkVersion = FBInstant.getSDKVersion(); // '3.0' 

     var playerID = FBInstant.player.getID();

});

抛出INVALID_OPERATION

返回Promise此 promise 将在 SDK 可以使用时被解析。


setLoadingProgress( )

报告游戏的初始加载进度。

参数

percentage数字介于 0 和 100 之间的数字。

示例

FBInstant.setLoadingProgress(50); // Assets are 50% loaded

返回void


getSupportedAPIs( )

提供客户端支持的 API 函数的列表。

示例

// This function should be called after FBInstant.initializeAsync()

// resolves.

FBInstant.getSupportedAPIs();

// ['getLocale', 'initializeAsync', 'player.getID', 'context.getType', ...]

返回数组<字符串>客户端显式支持的 API 函数列表。


getEntryPointData( )

返回与启动游戏的入口点相关的任何数据对象。

对象内容由开发者定义,可通过不同平台的入口点触发。对于较旧版本的移动客户端,以及没有与特定入口点相关的数据时,

此函数会返回 null。

示例

// This function should be called after FBInstant.initializeAsync()

// resolves.

const entryPointData = FBInstant.getEntryPointData();

返回对象与当前入口点相关的数据。


getEntryPointAsync( )

返回启动游戏的入口点

示例

// This function should be called after FBInstant.startGameAsync()

// resolves.

FBInstant.getEntryPointAsync().then(entrypoint => console.log(entrypoint));

// 'admin_message'

返回字符串用户启动游戏时所在的入口点的名称

仅当 FBInstant.startGameAsync() 被解析后才应调用此函数。


setSessionData( )

为当前环境设置与单个游戏会话相关的数据。

当游戏需要更新当前的会话数据时,应调用此函数。此会话数据可用于填充各种负载,如玩游戏 Webhook。

参数

sessionData对象一个随机数据对象,转变为字符串后,必须小于或等于 1000 个字符。

示例

FBInstant.setSessionData({coinsEarned: 10, eventsSeen: ['start', ...]});

返回void


startGameAsync( )

表示游戏已完成初始加载,并准备就绪可以开始游戏。当返回的 promise 被解析时,环境信息即为最新。

示例

FBInstant.startGameAsync().then(function() { 

     myGame.start();

});

抛出INVALID_PARAM

抛出CLIENT_UNSUPPORTED_OPERATION

返回Promise此 promise 将在游戏应该启动时被解析。


shareAsync( )

此函数会调用一个对话框,让用户以下列方式分享指定的内容:在 Messenger中发送消息,或在用户时间线上发布帖子。可以在分享中添加数据块,通过此次分享启动的每个游戏会话都可以通过 FBInstant.getEntryPointData() 访问此数据块。转变为字符串时,此数据必须小于或等于 1000 个字符。用户可以选择取消分享操作和关闭对话框,但无论用户实际是否分享了内容,返回的 promise 都将在对话框关闭时解析。

参数

payloadSharePayload,指定要分享的内容。详情请参阅示例。

示例

FBInstant.shareAsync({ 

     intent: 'REQUEST', 

     image: base64Picture, 

     text: 'X is asking for your help!', 

     data: { myReplayData: '...' },

}).then(function() { 

   // continue with the game.

});

抛出INVALID_PARAM

抛出NETWORK_FAILURE

抛出PENDING_REQUEST

抛出CLIENT_UNSUPPORTED_OPERATION

抛出INVALID_OPERATION

返回Promise此 promise 将在分享完成或取消时被解析。


updateAsync( )

向 Facebook 通知游戏内发生的更新。这会暂时将控制权移交给 Facebook,且 Facebook 将确定要根据更新内容采取什么操作。返回的 promise 将在 Facebook 把控制权返还给游戏时解析/拒绝。

参数

payloadUpdatePayload描述更新的负载。

示例

// This will post a custom update. If the game is played in a messenger

// chat thread, this will post a message into the thread with the specified

// image and text message. And when people launch the game from this

// message, those game sessions will be able to access the specified blob

// of data throughFBInstant.getEntryPointData().

FBInstant.updateAsync({ 

    action: 'CUSTOM', 

    cta: 'Join The Fight', 

    image: base64Picture, 

    text: {   

       default: 'X just invaded Y\'s village!',   

        localizations: {     

           ar_AR: 'X \u0641\u0642\u0637 \u063A\u0632\u062A ' +     

            '\u0642\u0631\u064A\u0629 Y!',     

           en_US: 'X just invaded Y\'s village!',     

           es_LA: '\u00A1X acaba de invadir el pueblo de Y!',   

       } 

    } 

    template: 'VILLAGE_INVASION', 

    data: { myReplayData: '...' }, 

    strategy: 'IMMEDIATE', 

    notification: 'NO_PUSH',

}).then(function() { 

   // closes the game after the update is posted. 

   FBInstant.quit();

});

抛出INVALID_PARAM

抛出PENDING_REQUEST

抛出INVALID_OPERATION

返回Promise此 promise 将在 Facebook 把控制权交还给游戏时被解析。


switchGameAsync( )

请求客户端切换到另一个小游戏。切换失败时,API 将拒绝,否则客户端将加载新游戏。

参数

appID字符串要切换到的小游戏相应的应用编号。应用必须为小游戏,且必须和当前游戏属于同一商家所有。要将不同游戏关联到相同商家,您可使用商务管理平台:https://developers.facebook.com/docs/apps/business-manager#update-business。data字符串可选的数据负载。这将设为要切换到的游戏的入口点数据。转变为字符串时,必须小于或等于 1000 个字符。

示例

FBInstant.switchGameAsync('12345678').catch(function (e) { 

     // Handle game change failure

});

抛出USER_INPUT

抛出INVALID_PARAM

抛出PENDING_REQUEST

抛出CLIENT_REQUIRES_UPDATE

返回Promise


quit( )

退出游戏。

示例

FBInstant.quit();

返回void


logEvent( )

通过 Facebook 分析记录应用事件。请参阅https://developers.facebook.com/docs/javascript/reference/v2.8#app_events详细了解 Fcaebook 分析。

参数

eventName字符串事件名称。必须为 2 到 40 个字符,且只能包含“_”、“-”、“ ”和字母数字字符。

valueToSum数字可选的数值,Facebook 分析利用此参数来计算总和。

parameters对象可选的对象,最多可包含25 个要与事件一同记录的键值对。键必须为 2 到 40 个字符,且只能包含“_”、“-”、“ ”和字母数字字符。值的长度必须小于 100 个字符。

示例

var logged = FBInstant.logEvent( 

    'my_custom_event', 

    42, 

     {custom_property: 'custom_value'},

);

返回APIError如果事件记录错误,将返回错误;否则返回 null。


onPause( )

设置发生暂停事件时将触发的回调。

参数

func函数发生暂停事件时将调用的函数。

示例

FBInstant.onPause(function() { 

    console.log('Pause event was triggered!');

})

返回void


getInterstitialAdAsync( )

尝试创建插屏广告的实例。此实例可在之后预载和显示。

参数

placementID字符串在 Audience Network 设置中设置的版位编号。

示例

FBInstant.getInterstitialAdAsync( 

     'my_placement_id',

).then(function(interstitial) { 

   interstitial.getPlacementID(); // 'my_placement_id'

});

抛出ADS_TOO_MANY_INSTANCES

抛出CLIENT_UNSUPPORTED_OPERATION

返回Promise此 promise 将在获得#adinstance时被解析;在获得#apierror时被拒绝(如果未能创建)。


getRewardedVideoAsync( )

尝试创建奖励式视频广告的实例。此实例可在之后预载和显示。

参数

placementID字符串在 Audience Network 设置中设置的版位编号。

示例

FBInstant.getRewardedVideoAsync( 

    'my_placement_id',

).then(function(rewardedVideo) { 

   rewardedVideo.getPlacementID(); // 'my_placement_id'

});

抛出ADS_TOO_MANY_INSTANCES

抛出CLIENT_UNSUPPORTED_OPERATION

返回Promise此 promise 将在获得#adinstance时被解析;在获得#apierror时被拒绝(如果未能创建)。


matchPlayerAsync( )

[封闭公测]尝试将当前玩家与等待他人加入游戏的其他玩家进行匹配。如果匹配成功,将为匹配的玩家创建一个新的 Messenger 群聊,且玩家的游戏环境将切换到该群聊。

参数

matchTag字符串玩家的可选额外信息,可用于将玩家加到具有相似玩家的群聊中。具有完全相同标签的玩家才会加入同一群聊。标签只能包含字母、数字和下划线,且长度不能超过 100 个字符。

switchContextWhenMatchedboolean可选的额外参数,指定当找到匹配时,是否将玩家立即切换到新环境。默认设置为 false,亦即玩家在匹配成功后,需要明确点击玩游戏按钮才会切换到新环境。

示例

FBInstant 

    .matchPlayerAsync('level1') 

    .then(function() {   

      console.log(FBInstant.context.getID());   

       // 12345 

});


FBInstant 

    .matchPlayerAsync() 

    .then(function() {   

      console.log(FBInstant.context.getID());   

       // 3456 

     });


FBInstant 

    .matchPlayerAsync(null, true) 

    .then(function() {   

      console.log(FBInstant.context.getID());   

      // 3456

});

抛出INVALID_PARAM

抛出NETWORK_FAILURE

抛出USER_INPUT

抛出PENDING_REQUEST

抛出CLIENT_UNSUPPORTED_OPERATION

抛出INVALID_OPERATION

返回Promise当玩家已加入群聊并切换到群聊环境时,此 promise 被解析。


checkCanPlayerMatchAsync( )

[封闭公测]

检查当前玩家是否符合 matchPlayerAsync API 的条件。

示例

FBInstant 

     .checkCanPlayerMatchAsync() 

     .then(canMatch => {   

        if (canMatch) {     

          FBInstant.matchPlayerAsync('level1');   

        } 

    });

抛出NETWORK_FAILURE

抛出CLIENT_UNSUPPORTED_OPERATION

返回Promise<boolean>当玩家符合与其他玩家匹配的条件时,此 promise 被解析为 true,否则解析为 false。


getLeaderboardAsync( )

获取这款小游戏中的特有排行榜。

参数

name字符串排行榜的名称。小游戏的每个排行榜必须具有唯一的名称。

示例

FBInstant.getLeaderboardAsync('my_awesome_leaderboard') 

     .then(leaderboard => {   

       console.log(leaderboard.getName()); // 'my_awesome_leaderboard' 

      });

抛出LEADERBOARD_NOT_FOUND

抛出NETWORK_FAILURE

抛出CLIENT_UNSUPPORTED_OPERATION

抛出INVALID_OPERATION

抛出INVALID_PARAM

返回Promise<排行榜>此 promise 在获得匹配的排行榜时被解析,在未找到匹配时被拒绝。


LocalizationsDict

代表特定字符串的语言设置与翻译之间的映射。每个属性均为可选且包含五个字符的 Facebook 语言代码,格式为 xx_XX。请参阅https://origincache.facebook.com/developers/resources/?id=FacebookLocales.xml,获取受支持的语言代码的完整列表。

类型:对象


APIError

小游戏 SDK 返回的 API 错误


code

相关的错误代码

类型:ErrorCodeType


message

描述错误的消息

类型:字符串


ConnectedPlayer

代表与当前玩家关联的玩家的信息。


getID( )

获取关联玩家的编号。

返回字符串关联玩家的编号


getName( )

获取玩家的全名。

返回字符串即玩家的全名


getPhoto( )

获取玩家公开头像的网址。

返回字符串玩家公开头像的网址


SignedPlayerInfo

代表玩家信息,并包含签名,

签名用于验证对应信息确实来源于 Facebook。


getPlayerID( )

获取玩家的编号。

示例

FBInstant.player.getSignedPlayerInfoAsync() 

    .then(function (result) {   

       result.getPlayerID(); // same value as FBInstant.player.getID() 

     });

返回字符串玩家的编号


getSignature( )

用于验证此对象确实来源于 Facebook 的签名。此字符串使用 base64url 编码,并根据 OAuth 2.0 协议使用 HMAC 版本的应用密钥签名。

您可以通过以下步骤进行验证:

1.将签名分为两个部分,以“.”字符隔开。

2.对第一部分(编码签名)执行以下替换操作:

              将短横线 ('-') 替换为加号 ('+')

              将下划线 ('_') 替换为正斜杠 ('/')

3.使用 base64url 编码对产生的字符串解码。

4.通过 base64url 编码对第二部分(响应负载)进行解码,第二部分应该是代表 JSON对象(包含下列字段)的字符串:

            algorithm — 始终等于 HMAC-SHA256

            issued_at — 发出此响应的 unix 时间戳。

            player_id — 玩家的唯一标识。

            request_payload — 调用 FBInstant.player.getSignedPlayerInfoAsync 时指定的 requestPayload 字符串。

5.请采用 HMAC SHA-256 和您的应用密钥散列处理整个响应负载字符串,并确定它等同于经编码的签名。

6.还建议您验证响应负载中的 issued_at 时间戳,确保请求是最近发出的。

应仅在您的服务器中进行签名验证。不要在客户端进行签名验证,因为客户端可能会泄漏您的应用密钥。

示例

//

// In your game's client

//

FBInstant.player.getSignedPlayerInfoAsync('my_payload') 

     .then(function (result) {   

       MyServer.send(result.getSignature());   

       // Example result.getSignature()                                                        

      //Eii6e636mz5J47sfqAYEK40jYAwoFqi3x5bxHkPG4Q4.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImlzc3VlZF9hdCI6M

        TUwMDM5ODY3NSwicGxheWVyX2lkIjoiMTI0OTUyNTMwMTc1MjIwMSIsInJlcXVlc3RfcGF5bG9hZCI6Im15X2ZpcnN

        0X3JlcXVlc3QifQ

   });

//

// In your server (node.js example)

//

const CryptoJS = require('crypto-js');

var firstpart = signedRequest.split('.')[0];

firstpart = firstpart.replace(/-/g, '+').replace(/_/g, '/');

const signature = CryptoJS.enc.Base64.parse(firstpart).toString();

const dataHash = CryptoJS.HmacSHA256(signedRequest.split('.')[1], '').toString();

var isValid = signature === dataHash;

const json = crypto.enc.Base64.parse(signedRequest.split('.')[1]).toString(crypto.enc.Utf8);

const encodedData = JSON.parse(json);

// Example encodedData:

// {

//  algorithm: 'HMAC-SHA256',

//  issued_at: 1520009634,

//  player_id: '123456789',

//  request_payload: 'my_payload'

//  }

返回字符串签名字符串。


ContextPlayer

代表与当前玩家在相同环境中玩游戏的玩家的信息。


getID( )

获取相同环境玩家的编号。

返回字符串相同环境玩家的编号


getName( )

获取经本地化显示的玩家姓名。

返回字符串经本地化显示的玩家姓名。


getPhoto( )

获取玩家公开头像的网址。

返回字符串玩家公开头像的网址


AdInstance

代表广告实例。


getPlacementID( )

返回此广告实例的 Audience Network 版位编号。


loadAsync( )

预加载广告。返回的 promise 将在预加载完成时被解析,在预加载失败时被拒绝。

示例

FBInstant.getInterstitialAdAsync( 

     'my_placement_id',

).then(function(interstitial) { 

  return interstitial.loadAsync();

}).then(function() { 

   // Ad loaded

});

抛出ADS_FREQUENT_LOAD

抛出ADS_NO_FILL

抛出INVALID_PARAM

抛出NETWORK_FAILURE

返回Promise


showAsync( )

代表广告。返回的 promise 将在用户观看完广告时被解析,在广告展示失败或用户在广告展示期间关闭广告时被拒绝。

示例

var ad = null;

FBInstant.getRewardedVideoAsync( 

     'my_placement_id',

).then(function(rewardedVideo) {

   ad = rewardedVideo; 

   return ad.loadAsync();

}).then(function() { 

   // Ad loaded 

   return ad.showAsync();

}).then(function() { 

   // Ad watched

});

抛出ADS_NOT_LOADED

抛出INVALID_PARAM

抛出NETWORK_FAILURE

返回Promise


排行榜

小游戏排行榜


getName( )

排行榜的名称。

示例

FBInstant.getLeaderboardAsync('my_leaderboard') 

    .then(function(leaderboard) {   

         console.log(leaderboard.getName()); // my_leaderboard 

     });

返回字符串


getContextID( )

与排行榜相关联环境的编号,如果排行榜未与特定环境关联,则为 null。

示例

FBInstant.getLeaderboardAsync('contextual_leaderboard') 

     .then(function(leaderboard) {   

       console.log(leaderboard.getContextID()); // 12345678 

      });


FBInstant.getLeaderboardAsync('global_leaderboard') 

     .then(function(leaderboard) {   

       console.log(leaderboard.getContextID()); // null 

      });

返回字符串


getEntryCountAsync( )

获取排行榜中玩家上榜分数的总数量。

示例

FBInstant.getLeaderboardAsync('my_leaderboard') 

     .then(function(leaderboard) {   

       return leaderboard.getEntryCountAsync(); 

      }) 

      .then(function(count) { console.log(count); }); // 24

抛出NETWORK_FAILURE

返回Promise<数字>玩家的唯一标识。


setScoreAsync( )

更新玩家的分数。如果玩家已有分数,只有新分数更好时,才会替换旧分数。注意:如果排行榜与特定环境关联,游戏必须处于该环境,才能为玩家设置分数。

参数

score数字玩家的新分数。必须为 64 位整数。

extraData字符串?= ion。与保存的分数关联的元数据。大小必须小于 2KB。

示例

FBInstant.getLeaderboardAsync('my_leaderboard') 

     .then(function(leaderboard) {   

       return leaderboard.setScoreAsync(42, '{race: "elf", level: 3}'); 

      }) 

      .then(function(entry) {   

        console.log(entry.getScore()); // 42   

        console.log(entry.getExtraData()); // '{race: "elf", level: 3}' 

       });

抛出LEADERBOARD_WRONG_CONTEXT

抛出NETWORK_FAILURE

抛出INVALID_PARAM

抛出INVALID_OPERATION

返回Promise<LeaderboardEntry>解析为更新后玩家在排行榜的当前上榜分数。


getPlayerEntryAsync( )

检索当前玩家的排行榜上榜分数,或在玩家尚无

上榜分数时返回 null。

示例

FBInstant.getLeaderboardAsync('my_leaderboard') 

    .then(function(leaderboard) {   

      return leaderboard.getPlayerEntryAsync(); 

     }) 

     .then(function(entry) {   

       console.log(entry.getRank()); // 2   

       console.log(entry.getScore()); // 42   

       console.log(entry.getExtraData()); // '{race: "elf", level: 3}' 

      });

抛出NETWORK_FAILURE

抛出INVALID_OPERATION

返回Promise<LeaderboardEntry>?解析为玩家在排行榜的当前上榜分数。


getEntriesAsync( )

检索一组排行榜上榜分数,按排行榜上的得分名次排序。

参数

count数字尝试从排行榜获取的上榜分数总数量。如果未指定,默认为 10。每条查询命令最多可获取100 个上榜分数。

offset数字从排行榜顶部检索上榜分数的偏移量。

示例

FBInstant.getLeaderboardAsync('my_leaderboard') 

     .then(function(leaderboard) {   

       return leaderboard.getEntriesAsync(); 

      }) 

      .then(function(entries) {   

        console.log(entries.length); // 10   

        console.log(entries[0].getRank()); // 1   

        console.log(entries[0].getScore()); // 42   

        console.log(entries[1].getRank()); // 2   

        console.log(entries[1].getScore()); // 40 

       });


FBInstant.getLeaderboardAsync('my_leaderboard') 

     .then(function(leaderboard) {   

        return leaderboard.getEntriesAsync(5, 3); 

      }) 

      .then(function(entries) {   

        console.log(entries.length); // 5   

        console.log(entries[0].getRank()); // 4    

        console.log(entries[0].getScore()); // 34   

        console.log(entries[1].getRank()); // 5   

        console.log(entries[1].getScore()); // 31 

       });

抛出NETWORK_FAILURE

返回Promise<数组<LeaderboardEntry>>解析为与查询条件相符的排行榜上榜分数。


商品

表示游戏的商品信息。

类型:对象

属性

title字符串商品的标题

productID字符串商品在游戏中的特定标识

description字符串商品说明

imageURI字符串商品相关图片的链接

price字符串商品的价格

priceCurrencyCode字符串商品的货币代码


ContextFilter

适用于环境选择操作的筛选条件。“NEW_CONTEXT_ONLY”—仅显示之前玩游戏未使用过的环境。“INCLUDE_EXISTING_CHALLENGES”— 包括“当前挑战”部分,显示玩家积极在其中玩游戏的环境。“NEW_PLAYERS_ONLY”— 在包含个人信息的部分,筛选出之前未玩过游戏的用户,

类型:("NEW_CONTEXT_ONLY"|"INCLUDE_EXISTING_CHALLENGES"|"NEW_PLAYERS_ONLY")


购买

表示游戏商品的单笔购买。

类型:对象

属性

developerPayload字符串开发者指定的字符串,在商品购买期间提供

paymentID字符串购买交易的标识

productID字符串商品在游戏中的特定标识

purchaseTime字符串购买发生时的 Unix 时间戳

purchaseToken字符串代表该笔购买的一个口令,可用来消费购买的商品

signedRequestSignedPurchaseRequest购买请求的服务器签名代码


平台

代表用户当前在哪个平台玩游戏。

类型:("IOS"|"ANDROID"|"WEB"|"MOBILE_WEB")


ContextSizeResponse

如果当前环境的规模介于对象中指定的 minSize 和 maxSize 值之间,answer 字段为 true,否则为 false。

类型:{answer:boolean, minSize:number?, maxSize:number?}


SharePayload

代表用户分享的内容。

类型:对象

属性

intent("INVITE"|"REQUEST"|"CHALLENGE"|"SHARE")表示分享的意图。

image字符串要分享的 base64 编码图片。

text字符串要分享的文本消息。

data对象要附加到分享中的数据块。通过分享开始的所有游戏会话都可以通过 FBInstant.getEntryPointData() 访问此数据块。


错误代码

小游戏 API 可能会返回的错误代码

属性

ADS_FREQUENT_LOAD字符串广告加载太频繁。

ADS_NO_FILL字符串我们无法向当前的用户投放广告。如果用户在设备中退订基于兴趣的广告,或我们没有广告可展示给该用户,就会出现这种情况

ADS_NOT_LOADED字符串尝试显示此前未成功加载的广告。

ADS_TOO_MANY_INSTANCES字符串同时展示的广告实例太多。建议您先加载和展示现有广告实例,再新建广告。

ANALYTICS_POST_EXCEPTION字符串分析 API 在尝试发布事件时遇到问题。

CLIENT_REQUIRES_UPDATE字符串[已停用] — 客户端要求获得更新,以便访问返回此结果的功能。如果在网页端返回这一结果,则意味着该网页客户端还不支持此功能。v5.0 及更高版本已停用这一代码,以便支持 CLIENT_UNSUPPORTED_OPERATION

CLIENT_UNSUPPORTED_OPERATION字符串客户端不支持当前操作。这可能是因为客户端版本或平台不提供相关支持,或不允许对游戏或玩家执行此操作。

INVALID_OPERATION字符串所请求的操作无效,或表示当前的游戏状态。这包括违反限制(如超出存储上限)或不适用于特定状态(如在独立的环境中针对特定环境发出请求)的情况。

INVALID_PARAM字符串传递给 API 的参数无效。可表示错误类型、参数的无效数字,或语义问题(例如,将不可序列化的对象传递到序列化函数)。

LEADERBOARD_NOT_FOUND字符串找不到所请求名称的排行榜。这是因为排行榜尚不存在,或其名称与游戏中登记的任何排行榜配置都不匹配。

LEADERBOARD_WRONG_CONTEXT字符串尝试写入的排行榜关联了不同于当前玩游戏环境的其他环境。

NETWORK_FAILURE字符串客户端处理网络请求时出现问题。这可能是由暂时性问题导致的,如玩家的网络连接中断。

PENDING_REQUEST字符串表示因存在与此请求冲突的一项请求而被拒绝。例如,当某个依赖于 Facebook 用户界面的请求处于待处理状态时,我们就会拒绝显示 Facebook 用户界面的其他任何调用。

SAME_CONTEXT字符串游戏尝试切换到当前环境。

UNKNOWN字符串发生了未知或未指定的问题。这是客户端未指定代码时返回的默认错误代码。

USER_INPUT字符串用户的选择导致被拒绝。例如,如果游戏调用环境切换对话框,而玩家关闭此对话框,则 promise 拒绝中就会包含此错误代码。

示例

FBInstant.startGameAsync().catch(function(e) { 

    console.log(e);

});

// {code: 'CLIENT_UNSUPPORTED_OPERATION', message: '...'}


UpdateAction

表示要执行的更新操作类型。

属性

CUSTOM字符串一项自定义更新,所有内容都由游戏指定。

LEADERBOARD字符串与小游戏排行榜相关的一项更新。


ErrorCodeType

小游戏错误代码,#errorcode中的一种

类型:字符串

SignedPurchaseRequest

类型:字符串

示例

Eii6e636mz5J47sfqAYEK40jYAwoFqi3x5bxHkPG4Q4.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImlzc3VlZF9hdCI6MTUwMD

M5ODY3NSwicGxheWVyX2lkIjoiMTI0OTUyNTMwMTc1MjIwMSIsInJlcXVlc3RfcGF5bG9hZCI6Im15X2ZpcnN0X3JlcXVlc3QifQ


PurchaseConfig

注册到游戏的商品的购买请求配置。

类型:对象

属性

productID字符串要购买商品的标识

developerPayload字符串由开发者指定的可选负载,包含在所返回购买的签名请求中。


CustomUpdatePayload

代表 FBInstant.updateAsync 的自定义更新。

类型:对象

属性

actionUpdateAction对于自定义更新,此属性应为“CUSTOM”。

template字符串此自定义更新所使用模板的编号。模板应在 fbapp-config.json 中预定义。请参阅[捆绑包配置文档]https://developers.facebook.com/docs/games/instant-games/bundle-config,获取有关 fbapp-config.json 的文档。

cta字符串?|LocalizableContent?)可选的行动号召按钮文本。默认情况下,我们会使用经本地化的“Play”作为按钮文本。若要提供自定义行动号召的本地化版本,应传递一个包含默认行动号召的对象作为“default”值,以及将语言键映射到翻译的另一个对象作为“localizations”值。

image字符串base64 编码图片的数据网址。

text字符串|LocalizableContent一条文本消息,或者是一个包含默认文本作为“default”值的对象以及另一个将语言键映射到翻译内容作为“localizations”值的对象。

data对象要附加到更新中的数据块。通过更新开始的所有游戏会话都可以通过 FBInstant.getEntryPointData() 访问此数据块。转变为字符串时,此数据块必须小于或等于 1000 个字符。

strategy字符串指定更新的发布方式。可以是下列方式之一:“IMMEDIATE”— 更新应立即发布。“LAST”— 更新应在游戏会话结束时发布。使用“LAST”策略发送的是最近发送的更新。“IMMEDIATE_CLEAR”— 更新将立即发布,并清除其他任何待处理的更新(如通过“LAST”策略发布的更新)。如果未指定策略,我们将默认为“IMMEDIATE”。

notification字符串指定自定义更新的通知设置。可以是“NO_PUSH”或“PUSH”,默认为“NO_PUSH”。仅将推送通知用于对接收人来说非常显著且可立即操作的更新。另请注意,并不一定会发送推送通知,具体取决于用户设置和平台政策。


LeaderboardUpdatePayload

表示 FBInstant.updateAsync 的一项排行榜更新。

类型:对象

属性

actionUpdateAction对于排行榜更新,此属性应为“LEADERBOARD”。文本。默认情况下,我们会使用经本地化的“Play Now”作为按钮文本。

name字符串所更新排行榜的名称。

text字符串可选的文本消息。如果未指定,将会提供一条经本地化的回退消息。


LocalizableContent

代表一个字符串,其中包含最终使用的本地化内容和默认值。

类型:对象

属性

default字符串要使用的字符串的默认值(查看者的语言设置不是 localizations 对象中的键时)。

localizationsLocalizationsDict指定每种语言设置中用于观看者的字符串。请参阅https://origincache.facebook.com/developers/resources/?id=FacebookLocales.xml,获取受支持的语言值的完整列表。


LeaderboardEntry

小游戏排行榜上的一个上榜分数


getScore( )

获取上榜分数的分值。

示例

leaderboard.setScoreAsync(9001) 

   .then(function(entry) {   

      console.log(entry.getScore()); // 9001 

    });

返回数字返回整数的分数。


getFormattedScore( )

获取与上榜分数相关的分值,采用与排行榜相同的分值格式。

示例

leaderboard.setScoreAsync(9001) 

    .then(function(entry) {   

      console.log(entry.getFormattedScore()); // '90.01 meters' 

     });

返回字符串返回有格式的分数。


getTimestamp( )

获取排行榜上榜分数的上次更新时间戳。

示例

leaderboard.setScoreAsync(9001) 

   .then(function(entry) {   

     console.log(entry.getTimestamp()); // 1515806355 

    });

返回数字返回 Unix 时间戳。


getRank( )

获取玩家分数在排行榜中的排行。

示例

leaderboard.setScoreAsync(9001) 

    .then(function(entry) {   

       console.log(entry.getRank()); // 2 

     });

返回数字返回上榜分数在排行榜的排行。


getExtraData( )

获取与分数相关的开发者指定负载,或在没有设定时返回 null。

示例

leaderboard.setScoreAsync(42, '{race: "elf", level: 3}'); 

    .then(function(entry) {   

      console.log(entry.getExtraData()); // '{race: "elf", level: 3}' 

     });

返回字符串与分数相关的开发者指定负载,为可选参数。


getPlayer( )

获取与上榜分数相关玩家的信息。

示例

leaderboard.setScoreAsync(9001) 

   .then(function(entry) {   

     console.log(entry.getPlayer().getName()); // Sally 

    });

返回LeaderboardPlayer


LeaderboardPlayer

与上榜分数相关玩家的详情。


getName( )

获取经本地化显示的玩家姓名。

示例

leaderboard.setScoreAsync(9001) 

   .then(function(entry) {   

     console.log(entry.getPlayer().getName()); // Sally 

    });

返回字符串经本地化显示的玩家姓名。


getPhoto( )

返回玩家公开头像的网址。

示例

leaderboard.setScoreAsync(9001) 

    .then(function(entry) {   

      console.log(entry.getPlayer().getPhoto()); //  

     });

返回字符串玩家公开头像的网址。


getID( )

获取玩家在游戏中的唯一标识。

示例

leaderboard.setScoreAsync(9001) 

   .then(function(entry) {    

     console.log(entry.getPlayer().getID()); // 12345678 

    });

返回字符串玩家在游戏中的标识。

另外我创建了一个 Facebook Instant Game   交流QQ群:814298516


欢迎同行们加入讨论技术

猜你喜欢

转载自blog.csdn.net/box_square/article/details/80900888