@maoyugames/phaser-framework 1.0.12 → 1.0.16
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.
- package/dist/platform/tiktok.js +143 -41
- package/package.json +1 -1
package/dist/platform/tiktok.js
CHANGED
|
@@ -10,24 +10,50 @@ function requireTT(capability) {
|
|
|
10
10
|
if (!hasTT()) throw new PlatformUnsupportedError("tiktok", capability);
|
|
11
11
|
}
|
|
12
12
|
var TikTokAuth = class {
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
|
|
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
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
|
30
|
-
// /v2/user/info/ 取(
|
|
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
|
}
|
|
@@ -100,8 +126,48 @@ var TikTokAds = class {
|
|
|
100
126
|
onError(e?.message ?? "show rejected");
|
|
101
127
|
});
|
|
102
128
|
}
|
|
103
|
-
|
|
104
|
-
|
|
129
|
+
// 插页广告:官方文档 createInterstitialAd 自 SDK 0.3.0;当前反编译版 sdk.js 未见此 API,
|
|
130
|
+
// 真机 SDK 版本可能更高。typeof 检测:SDK 有就用(create → onClose/onError → show),没有降级 failed。
|
|
131
|
+
showInterstitial(adUnitId) {
|
|
132
|
+
requireTT("ads.showInterstitial");
|
|
133
|
+
const create = TTMinis.game.createInterstitialAd;
|
|
134
|
+
if (typeof create !== "function") return Promise.resolve("failed");
|
|
135
|
+
return new Promise((resolve) => {
|
|
136
|
+
let settled = false;
|
|
137
|
+
const done = (r) => {
|
|
138
|
+
if (!settled) {
|
|
139
|
+
settled = true;
|
|
140
|
+
resolve(r);
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
try {
|
|
144
|
+
const ad = create.call(TTMinis.game, { adUnitId });
|
|
145
|
+
if (!ad || typeof ad.show !== "function") {
|
|
146
|
+
done("failed");
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
try {
|
|
150
|
+
ad.onClose(() => done("closed"));
|
|
151
|
+
} catch {
|
|
152
|
+
}
|
|
153
|
+
if (typeof ad.onError === "function") {
|
|
154
|
+
try {
|
|
155
|
+
ad.onError((res) => {
|
|
156
|
+
console.warn("[ads.showInterstitial] error:", res?.error?.error_msg);
|
|
157
|
+
done("failed");
|
|
158
|
+
});
|
|
159
|
+
} catch {
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
void ad.show().catch((e) => {
|
|
163
|
+
console.warn("[ads.showInterstitial] show rejected:", e?.message);
|
|
164
|
+
done("failed");
|
|
165
|
+
});
|
|
166
|
+
} catch (e) {
|
|
167
|
+
console.warn("[ads.showInterstitial] create threw:", e?.message);
|
|
168
|
+
done("failed");
|
|
169
|
+
}
|
|
170
|
+
});
|
|
105
171
|
}
|
|
106
172
|
};
|
|
107
173
|
var TikTokShortcut = class {
|
|
@@ -190,27 +256,40 @@ var TikTokMission = class {
|
|
|
190
256
|
}
|
|
191
257
|
};
|
|
192
258
|
var TikTokPayment = class {
|
|
193
|
-
|
|
259
|
+
// TikTok IAP(2026-05-29 飞书接入指南):后端预下单拿 trade_order_id,前端 game.pay 拉起收银台。
|
|
260
|
+
// purchase 的 productId 参数在 TikTok 下被用作 trade_order_id(业务后端已下单);也兼容从
|
|
261
|
+
// extra.orderId / extra.tradeOrderId 取(ShopModule 传的是 {orderId: trade_order_id})。
|
|
262
|
+
// resolve 仅表示「客户端支付面板流程结束」,真正发货由 webhook + 业务层轮询后端订单状态确认。
|
|
263
|
+
purchase(productId, extra) {
|
|
194
264
|
requireTT("payment.purchase");
|
|
195
|
-
const
|
|
196
|
-
return {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
265
|
+
const tradeOrderId = extra?.orderId ?? extra?.tradeOrderId ?? productId;
|
|
266
|
+
return new Promise((resolve, reject) => {
|
|
267
|
+
let settled = false;
|
|
268
|
+
try {
|
|
269
|
+
TTMinis.game.pay({
|
|
270
|
+
trade_order_id: tradeOrderId,
|
|
271
|
+
success: () => {
|
|
272
|
+
if (settled) return;
|
|
273
|
+
settled = true;
|
|
274
|
+
resolve({ productId, transactionId: tradeOrderId, receipt: tradeOrderId, raw: { trade_order_id: tradeOrderId } });
|
|
275
|
+
},
|
|
276
|
+
fail: (err) => {
|
|
277
|
+
if (settled) return;
|
|
278
|
+
settled = true;
|
|
279
|
+
reject(new Error(`TikTok pay failed: ${err?.errMsg ?? "unknown"}`));
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
} catch (e) {
|
|
283
|
+
if (!settled) {
|
|
284
|
+
settled = true;
|
|
285
|
+
reject(e);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
});
|
|
202
289
|
}
|
|
290
|
+
// TikTok H5 SDK 未确认 getUnfinishedPurchases;掉单恢复靠后端订单状态查询 + webhook,这里返空。
|
|
203
291
|
async restore() {
|
|
204
|
-
|
|
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
|
-
}));
|
|
292
|
+
return [];
|
|
214
293
|
}
|
|
215
294
|
};
|
|
216
295
|
var TikTokDevice = class {
|
|
@@ -241,12 +320,35 @@ var TikTokDevice = class {
|
|
|
241
320
|
const res = await TTMinis.game.getClipboardData();
|
|
242
321
|
return res?.data ?? "";
|
|
243
322
|
}
|
|
244
|
-
|
|
323
|
+
// shareAppMessage 是 callback 式(2026-05-30 反编译核对),不是 Promise;这里包成 Promise。
|
|
324
|
+
share(payload) {
|
|
245
325
|
requireTT("device.share");
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
326
|
+
return new Promise((resolve, reject) => {
|
|
327
|
+
let settled = false;
|
|
328
|
+
try {
|
|
329
|
+
TTMinis.game.shareAppMessage({
|
|
330
|
+
title: payload.title,
|
|
331
|
+
imageUrl: payload.imageUrl,
|
|
332
|
+
query: payload.query,
|
|
333
|
+
success: () => {
|
|
334
|
+
if (!settled) {
|
|
335
|
+
settled = true;
|
|
336
|
+
resolve();
|
|
337
|
+
}
|
|
338
|
+
},
|
|
339
|
+
fail: (err) => {
|
|
340
|
+
if (!settled) {
|
|
341
|
+
settled = true;
|
|
342
|
+
reject(new Error(`share failed: ${err?.errMsg ?? "unknown"}`));
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
} catch (e) {
|
|
347
|
+
if (!settled) {
|
|
348
|
+
settled = true;
|
|
349
|
+
reject(e);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
250
352
|
});
|
|
251
353
|
}
|
|
252
354
|
};
|