@maoyugames/phaser-framework 1.0.12 → 1.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import { d as IPlatform, r as PlatformName, S as SafeArea, v as SystemInfo, L as LaunchOptions, k as IPlatformNet, o as IPlatformStorage, i as IPlatformLifecycle, g as IPlatformAuth, e as IPlatformAds, l as IPlatformPayment, h as IPlatformDevice, f as IPlatformAnalytics, m as IPlatformShortcut, j as IPlatformMission, P as PlatformInfo } from './types-WJYVtDfo.js';
1
+ import { d as IPlatform, r as PlatformName, S as SafeArea, v as SystemInfo, L as LaunchOptions, k as IPlatformNet, o as IPlatformStorage, i as IPlatformLifecycle, g as IPlatformAuth, e as IPlatformAds, l as IPlatformPayment, h as IPlatformDevice, f as IPlatformAnalytics, m as IPlatformShortcut, j as IPlatformMission, P as PlatformInfo } from './types-BceYZWGr.js';
2
2
 
3
3
  /**
4
4
  * 平台抽象基类:封装"有 DOM/BOM 的环境"通用实现,供
package/dist/cli/index.js CHANGED
@@ -318,7 +318,7 @@ function escapeAttr(s) {
318
318
  }
319
319
 
320
320
  // src/cli/shells/facebook.ts
321
- var DEFAULT_FB_SDK_VERSION = "7.1";
321
+ var DEFAULT_FB_SDK_VERSION = "8.0";
322
322
  function renderFacebookHtml(cfg, scriptSrc) {
323
323
  const title = escapeHtml(cfg?.appName ?? "Facebook Instant Game");
324
324
  const sdkVersion = (cfg?.fbSdkVersion ?? DEFAULT_FB_SDK_VERSION).trim();
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { b as HttpRequestOptions, U as Unsubscribe, H as Handler, p as LogLevel, A as AdResult, t as PurchaseResult, q as LoginResult, d as IPlatform, i as IPlatformLifecycle, S as SafeArea } from './types-WJYVtDfo.js';
2
- export { a as HttpMethod, c as HttpResponse, I as IDisposable, e as IPlatformAds, f as IPlatformAnalytics, g as IPlatformAuth, h as IPlatformDevice, j as IPlatformMission, k as IPlatformNet, l as IPlatformPayment, m as IPlatformShortcut, n as IPlatformSocket, o as IPlatformStorage, L as LaunchOptions, P as PlatformInfo, r as PlatformName, s as PlatformUnsupportedError, R as Result, u as SocketOptions, v as SystemInfo, V as Vec2, w as err, x as ok } from './types-WJYVtDfo.js';
1
+ import { b as HttpRequestOptions, U as Unsubscribe, H as Handler, p as LogLevel, A as AdResult, t as PurchaseResult, q as LoginResult, d as IPlatform, i as IPlatformLifecycle, S as SafeArea } from './types-BceYZWGr.js';
2
+ export { a as HttpMethod, c as HttpResponse, I as IDisposable, e as IPlatformAds, f as IPlatformAnalytics, g as IPlatformAuth, h as IPlatformDevice, j as IPlatformMission, k as IPlatformNet, l as IPlatformPayment, m as IPlatformShortcut, n as IPlatformSocket, o as IPlatformStorage, L as LaunchOptions, P as PlatformInfo, r as PlatformName, s as PlatformUnsupportedError, R as Result, u as SocketOptions, v as SystemInfo, V as Vec2, w as err, x as ok } from './types-BceYZWGr.js';
3
3
  import Phaser from 'phaser';
4
4
 
5
5
  /**
@@ -1,5 +1,5 @@
1
- import { r as PlatformName, h as IPlatformDevice, i as IPlatformLifecycle } from '../types-WJYVtDfo.js';
2
- import { B as BasePlatform } from '../BasePlatform-CwVOo3_q.js';
1
+ import { r as PlatformName, h as IPlatformDevice, i as IPlatformLifecycle } from '../types-BceYZWGr.js';
2
+ import { B as BasePlatform } from '../BasePlatform-Bod6yNYx.js';
3
3
 
4
4
  /**
5
5
  * Capacitor(原生 WebView 容器)平台适配器。
@@ -1,5 +1,5 @@
1
- import { r as PlatformName, o as IPlatformStorage, g as IPlatformAuth, e as IPlatformAds, l as IPlatformPayment, h as IPlatformDevice, i as IPlatformLifecycle } from '../types-WJYVtDfo.js';
2
- import { B as BasePlatform } from '../BasePlatform-CwVOo3_q.js';
1
+ import { r as PlatformName, o as IPlatformStorage, g as IPlatformAuth, e as IPlatformAds, l as IPlatformPayment, h as IPlatformDevice, m as IPlatformShortcut, i as IPlatformLifecycle } from '../types-BceYZWGr.js';
2
+ import { B as BasePlatform } from '../BasePlatform-Bod6yNYx.js';
3
3
 
4
4
  /**
5
5
  * Facebook Instant Games 平台适配器。
@@ -26,6 +26,7 @@ declare class FacebookPlatform extends BasePlatform {
26
26
  readonly ads: IPlatformAds;
27
27
  readonly payment: IPlatformPayment;
28
28
  readonly device: IPlatformDevice;
29
+ readonly shortcut: IPlatformShortcut;
29
30
  readonly lifecycle: IPlatformLifecycle;
30
31
  init(): Promise<void>;
31
32
  }
@@ -93,6 +93,11 @@ var FacebookAuth = class {
93
93
  if (!name && !photo) return null;
94
94
  return { nickname: name ?? "", avatarUrl: photo ?? "" };
95
95
  }
96
+ // FB 的 player 信息(getName/getPhoto)无需额外授权弹窗即可读(与 TikTok 需 explicit authorize
97
+ // 拿 user.info.basic 不同)。authorize 直接复用 login() 的结果返回,业务层「按需引导授权」逻辑通用。
98
+ authorize(_scope) {
99
+ return this.login();
100
+ }
96
101
  };
97
102
  var FacebookAds = class {
98
103
  constructor() {
@@ -144,6 +149,37 @@ var FacebookAds = class {
144
149
  }
145
150
  }
146
151
  };
152
+ var FacebookShortcut = class {
153
+ check() {
154
+ if (!hasFB() || typeof FBInstant.canCreateShortcutAsync !== "function") {
155
+ return Promise.resolve(false);
156
+ }
157
+ try {
158
+ return FBInstant.canCreateShortcutAsync().then(
159
+ (ok) => !!ok,
160
+ () => false
161
+ );
162
+ } catch {
163
+ return Promise.resolve(false);
164
+ }
165
+ }
166
+ add() {
167
+ if (!hasFB() || typeof FBInstant.createShortcutAsync !== "function") {
168
+ return Promise.resolve(false);
169
+ }
170
+ try {
171
+ return FBInstant.createShortcutAsync().then(
172
+ () => true,
173
+ () => false
174
+ );
175
+ } catch {
176
+ return Promise.resolve(false);
177
+ }
178
+ }
179
+ getMissionReward() {
180
+ return Promise.resolve({ canReceive: false });
181
+ }
182
+ };
147
183
  var FacebookPayment = class {
148
184
  async purchase(productId, extra) {
149
185
  requireFB("payment.purchase");
@@ -224,6 +260,9 @@ var FacebookPlatform = class extends BasePlatform {
224
260
  __publicField(this, "ads", new FacebookAds());
225
261
  __publicField(this, "payment", new FacebookPayment());
226
262
  __publicField(this, "device", new FacebookDevice());
263
+ __publicField(this, "shortcut", new FacebookShortcut());
264
+ // mission 不实现(FB 无"侧边栏入口任务"概念,TikTok 特有);保持 undefined,
265
+ // 业务层 App.platform.mission?.startEntrance() 会安全跳过。
227
266
  __publicField(this, "lifecycle", new FacebookLifecycle(
228
267
  () => this.getLaunchOptions()
229
268
  ));
@@ -1,5 +1,5 @@
1
- import { r as PlatformName, g as IPlatformAuth, e as IPlatformAds, l as IPlatformPayment, h as IPlatformDevice, f as IPlatformAnalytics, m as IPlatformShortcut, j as IPlatformMission, i as IPlatformLifecycle } from '../types-WJYVtDfo.js';
2
- import { B as BasePlatform } from '../BasePlatform-CwVOo3_q.js';
1
+ import { r as PlatformName, g as IPlatformAuth, e as IPlatformAds, l as IPlatformPayment, h as IPlatformDevice, f as IPlatformAnalytics, m as IPlatformShortcut, j as IPlatformMission, i as IPlatformLifecycle } from '../types-BceYZWGr.js';
2
+ import { B as BasePlatform } from '../BasePlatform-Bod6yNYx.js';
3
3
 
4
4
  /**
5
5
  * TikTok Mini Games(Minis)平台适配器。
@@ -10,27 +10,84 @@ function requireTT(capability) {
10
10
  if (!hasTT()) throw new PlatformUnsupportedError("tiktok", capability);
11
11
  }
12
12
  var TikTokAuth = class {
13
- // TikTok H5 SDK 实测(2026-05-28 反编译 connect.tiktok-minis.com/game/sdk.js)
14
- // **没有 game.login 也没有 game.getUserInfo**——这两个 API 是抖音(国内)小游戏的协议,
15
- // TikTok 海外走 OAuth code 流程:authorizeOpenContext({get_status_only:false}) 弹授权页拿 code,
16
- // 后端用 code + client_secret 调 open.tiktokapis.com/v2/oauth/token/ + /v2/user/info/ 拿 user info
17
- async login() {
13
+ // 登录用 game.login(静默登录,2026-05-29 核对 SDK + 官方接入指南 §2 确认):它是 SDK 的
14
+ // class method,返回 authResponse.code,后端用此 code /v2/oauth/token/ 换 access_token+open_id。
15
+ // 早先误用 authorizeOpenContext 的 code(非标准 OAuth code),后端换 token 报 invalid_request:
16
+ // malformed,导致登录全废 一切需鉴权功能(购买/排行榜/同步)401。已纠正为 game.login
17
+ // game.login 是 callback 式({success,fail,complete}),这里包成 Promise。
18
+ login() {
18
19
  requireTT("auth.login");
19
- let res = await TTMinis.game.authorizeOpenContext({ get_status_only: true });
20
- if (!res?.is_success || !res?.code) {
21
- res = await TTMinis.game.authorizeOpenContext({ get_status_only: false });
22
- }
23
- if (!res?.is_success || !res?.code) {
24
- const e = res?.error;
25
- throw new Error(`TikTok authorize failed: ${e?.error_msg ?? "unknown"} (code=${e?.error_code ?? "NA"})`);
26
- }
27
- return { code: res.code, raw: res };
20
+ return new Promise((resolve, reject) => {
21
+ let settled = false;
22
+ const timer = setTimeout(() => {
23
+ if (settled) return;
24
+ settled = true;
25
+ reject(new Error("TikTok login timeout (no callback in 10s)"));
26
+ }, 1e4);
27
+ const finish = (fn) => {
28
+ if (settled) return;
29
+ settled = true;
30
+ clearTimeout(timer);
31
+ fn();
32
+ };
33
+ const onResult = (res) => {
34
+ const code = res?.code ?? res?.authResponse?.code ?? "";
35
+ finish(
36
+ () => code ? resolve({ code, raw: res }) : reject(new Error(`TikTok login failed: ${JSON.stringify(res?.error ?? res ?? "no code")}`))
37
+ );
38
+ };
39
+ try {
40
+ TTMinis.game.login({
41
+ success: onResult,
42
+ fail: (err) => finish(() => reject(new Error(`TikTok login fail: ${err?.errMsg ?? JSON.stringify(err)}`)))
43
+ });
44
+ } catch (e) {
45
+ try {
46
+ TTMinis.game.login(
47
+ (r) => onResult(r)
48
+ );
49
+ } catch {
50
+ finish(() => reject(e));
51
+ }
52
+ }
53
+ });
28
54
  }
29
- // TikTok H5 SDK 没有客户端 user info API。nickname/avatar 必须由后端用 access_token 调
30
- // /v2/user/info/ 取(scope=user.info.basic),客户端拿到的 user 已含这些字段。
55
+ // TikTok H5 SDK 没有客户端 user info API。nickname/avatar 由后端用 access_token 调
56
+ // /v2/user/info/ 取(需 explicit authorize 的 user.info.basic scope),客户端拿到的 user 已含。
31
57
  async getProfile() {
32
58
  return null;
33
59
  }
60
+ // 显式授权(game.authorize):弹 TikTok 授权页拿带 scope 的 code,后端换 token 后调 /v2/user/info/
61
+ // 取 nickname/avatar。callback 式,包成 Promise + 10s 超时(同 login,防永久 pending)。
62
+ authorize(scope = "user.info.basic") {
63
+ requireTT("auth.authorize");
64
+ return new Promise((resolve, reject) => {
65
+ let settled = false;
66
+ const timer = setTimeout(() => {
67
+ if (settled) return;
68
+ settled = true;
69
+ reject(new Error("TikTok authorize timeout"));
70
+ }, 1e4);
71
+ const finish = (fn) => {
72
+ if (settled) return;
73
+ settled = true;
74
+ clearTimeout(timer);
75
+ fn();
76
+ };
77
+ try {
78
+ TTMinis.game.authorize({
79
+ scope,
80
+ success: (res) => {
81
+ const code = res?.code ?? res?.authResponse?.code ?? "";
82
+ finish(() => code ? resolve({ code, raw: res }) : reject(new Error("authorize: no code")));
83
+ },
84
+ fail: (err) => finish(() => reject(new Error(`TikTok authorize fail: ${err?.errMsg ?? JSON.stringify(err)}`)))
85
+ });
86
+ } catch (e) {
87
+ finish(() => reject(e));
88
+ }
89
+ });
90
+ }
34
91
  };
35
92
  var TikTokAds = class {
36
93
  // TikTok H5 SDK 只有 createRewardedVideoAd(没有 preload/show/Interstitial 单独 API,
@@ -100,8 +157,48 @@ var TikTokAds = class {
100
157
  onError(e?.message ?? "show rejected");
101
158
  });
102
159
  }
103
- async showInterstitial(_adUnitId) {
104
- return "failed";
160
+ // 插页广告:官方文档 createInterstitialAd 自 SDK 0.3.0;当前反编译版 sdk.js 未见此 API,
161
+ // 真机 SDK 版本可能更高。typeof 检测:SDK 有就用(create → onClose/onError → show),没有降级 failed
162
+ showInterstitial(adUnitId) {
163
+ requireTT("ads.showInterstitial");
164
+ const create = TTMinis.game.createInterstitialAd;
165
+ if (typeof create !== "function") return Promise.resolve("failed");
166
+ return new Promise((resolve) => {
167
+ let settled = false;
168
+ const done = (r) => {
169
+ if (!settled) {
170
+ settled = true;
171
+ resolve(r);
172
+ }
173
+ };
174
+ try {
175
+ const ad = create.call(TTMinis.game, { adUnitId });
176
+ if (!ad || typeof ad.show !== "function") {
177
+ done("failed");
178
+ return;
179
+ }
180
+ try {
181
+ ad.onClose(() => done("closed"));
182
+ } catch {
183
+ }
184
+ if (typeof ad.onError === "function") {
185
+ try {
186
+ ad.onError((res) => {
187
+ console.warn("[ads.showInterstitial] error:", res?.error?.error_msg);
188
+ done("failed");
189
+ });
190
+ } catch {
191
+ }
192
+ }
193
+ void ad.show().catch((e) => {
194
+ console.warn("[ads.showInterstitial] show rejected:", e?.message);
195
+ done("failed");
196
+ });
197
+ } catch (e) {
198
+ console.warn("[ads.showInterstitial] create threw:", e?.message);
199
+ done("failed");
200
+ }
201
+ });
105
202
  }
106
203
  };
107
204
  var TikTokShortcut = class {
@@ -190,27 +287,40 @@ var TikTokMission = class {
190
287
  }
191
288
  };
192
289
  var TikTokPayment = class {
193
- async purchase(productId, extra) {
290
+ // TikTok IAP(2026-05-29 飞书接入指南):后端预下单拿 trade_order_id,前端 game.pay 拉起收银台。
291
+ // purchase 的 productId 参数在 TikTok 下被用作 trade_order_id(业务后端已下单);也兼容从
292
+ // extra.orderId / extra.tradeOrderId 取(ShopModule 传的是 {orderId: trade_order_id})。
293
+ // resolve 仅表示「客户端支付面板流程结束」,真正发货由 webhook + 业务层轮询后端订单状态确认。
294
+ purchase(productId, extra) {
194
295
  requireTT("payment.purchase");
195
- const res = await TTMinis.game.requestPayment({ productId, ...extra ?? {} });
196
- return {
197
- productId: res.productId ?? productId,
198
- transactionId: res.transactionId ?? "",
199
- receipt: res.receipt ?? "",
200
- raw: res
201
- };
296
+ const tradeOrderId = extra?.orderId ?? extra?.tradeOrderId ?? productId;
297
+ return new Promise((resolve, reject) => {
298
+ let settled = false;
299
+ try {
300
+ TTMinis.game.pay({
301
+ trade_order_id: tradeOrderId,
302
+ success: () => {
303
+ if (settled) return;
304
+ settled = true;
305
+ resolve({ productId, transactionId: tradeOrderId, receipt: tradeOrderId, raw: { trade_order_id: tradeOrderId } });
306
+ },
307
+ fail: (err) => {
308
+ if (settled) return;
309
+ settled = true;
310
+ reject(new Error(`TikTok pay failed: ${err?.errMsg ?? "unknown"}`));
311
+ }
312
+ });
313
+ } catch (e) {
314
+ if (!settled) {
315
+ settled = true;
316
+ reject(e);
317
+ }
318
+ }
319
+ });
202
320
  }
321
+ // TikTok H5 SDK 未确认 getUnfinishedPurchases;掉单恢复靠后端订单状态查询 + webhook,这里返空。
203
322
  async restore() {
204
- requireTT("payment.restore");
205
- const fn = TTMinis.game.getUnfinishedPurchases;
206
- if (!fn) return [];
207
- const list = await fn.call(TTMinis.game) ?? [];
208
- return list.map((res) => ({
209
- productId: res.productId,
210
- transactionId: res.transactionId ?? "",
211
- receipt: res.receipt ?? "",
212
- raw: res
213
- }));
323
+ return [];
214
324
  }
215
325
  };
216
326
  var TikTokDevice = class {
@@ -241,12 +351,35 @@ var TikTokDevice = class {
241
351
  const res = await TTMinis.game.getClipboardData();
242
352
  return res?.data ?? "";
243
353
  }
244
- async share(payload) {
354
+ // shareAppMessage 是 callback 式(2026-05-30 反编译核对),不是 Promise;这里包成 Promise。
355
+ share(payload) {
245
356
  requireTT("device.share");
246
- await TTMinis.game.shareAppMessage({
247
- title: payload.title,
248
- imageUrl: payload.imageUrl,
249
- query: payload.query
357
+ return new Promise((resolve, reject) => {
358
+ let settled = false;
359
+ try {
360
+ TTMinis.game.shareAppMessage({
361
+ title: payload.title,
362
+ imageUrl: payload.imageUrl,
363
+ query: payload.query,
364
+ success: () => {
365
+ if (!settled) {
366
+ settled = true;
367
+ resolve();
368
+ }
369
+ },
370
+ fail: (err) => {
371
+ if (!settled) {
372
+ settled = true;
373
+ reject(new Error(`share failed: ${err?.errMsg ?? "unknown"}`));
374
+ }
375
+ }
376
+ });
377
+ } catch (e) {
378
+ if (!settled) {
379
+ settled = true;
380
+ reject(e);
381
+ }
382
+ }
250
383
  });
251
384
  }
252
385
  };
@@ -1,5 +1,5 @@
1
- import { r as PlatformName, h as IPlatformDevice } from '../types-WJYVtDfo.js';
2
- import { B as BasePlatform } from '../BasePlatform-CwVOo3_q.js';
1
+ import { r as PlatformName, h as IPlatformDevice } from '../types-BceYZWGr.js';
2
+ import { B as BasePlatform } from '../BasePlatform-Bod6yNYx.js';
3
3
 
4
4
  /**
5
5
  * Web(普通浏览器 / H5)平台适配器。
@@ -1,4 +1,4 @@
1
- import { d as IPlatform, k as IPlatformNet, o as IPlatformStorage, i as IPlatformLifecycle, g as IPlatformAuth, e as IPlatformAds, l as IPlatformPayment, h as IPlatformDevice, P as PlatformInfo, L as LaunchOptions } from '../types-WJYVtDfo.js';
1
+ import { d as IPlatform, k as IPlatformNet, o as IPlatformStorage, i as IPlatformLifecycle, g as IPlatformAuth, e as IPlatformAds, l as IPlatformPayment, h as IPlatformDevice, P as PlatformInfo, L as LaunchOptions } from '../types-BceYZWGr.js';
2
2
 
3
3
  /**
4
4
  * 微信小游戏平台适配器。
@@ -169,6 +169,11 @@ interface IPlatformAuth {
169
169
  nickname: string;
170
170
  avatarUrl: string;
171
171
  } | null>;
172
+ /**
173
+ * 显式授权(弹授权页),返回带额外 scope 的 code,后端换 token 后可拿 nickname/avatar。
174
+ * 平台不支持时为 undefined。用于「按需引导用户授权显示昵称」(如首次进排行榜)。
175
+ */
176
+ authorize?(scope?: string): Promise<LoginResult>;
172
177
  }
173
178
  /** 广告 */
174
179
  type AdResult = 'completed' | 'skipped' | 'failed' | 'closed';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maoyugames/phaser-framework",
3
- "version": "1.0.12",
3
+ "version": "1.0.18",
4
4
  "description": "多平台 Phaser 游戏框架:业务/底层分离,HTTP/WebSocket/KCP,Web/TikTok/微信/Facebook/App 隔离打包",
5
5
  "type": "module",
6
6
  "license": "MIT",