feat: 新手礼包

This commit is contained in:
guanchao
2026-09-09 19:27:42 +08:00
parent 4e0378577d
commit 1b8cd1f557
38 changed files with 3408 additions and 2230 deletions
+6 -2
View File
@@ -474,7 +474,9 @@ export class GameConfig {
iosReviveOrder: string; //ios订单号复活
iosStarterOrder: string; //ios订单号新手
iosPassCheckOrder: string; // ios通行证订单
starter_packTime: number; //新手礼包活动时间
starter_packTime: number; // 新手礼包截止时间,秒
starterPackServerOffset: number; // 服务端时间与本地时间差,毫秒
starterPackPurchased: boolean;
wxFriend: boolean; //微信好友信息授权
wxUserInfo: boolean; //微信用户信息授权
winState: boolean; //是否延续连胜状态
@@ -685,7 +687,9 @@ export class GameConfig {
iosReviveOrder: "", //ios订单号复活
iosStarterOrder: "", //ios订单号新手
iosPassCheckOrder: "", // ios通行证订单
starter_packTime: 0, //新手礼包活动时间
starter_packTime: 0, // 新手礼包截止时间
starterPackServerOffset: 0,
starterPackPurchased: false,
wxFriend: false, //微信好友信息授权
wxUserInfo: false, //微信用户信息授权
winState: false, //是否延续连胜状态
@@ -0,0 +1,37 @@
/** Purchases and login compensation use the same client-owned reward. */
export function starterPackReward() {
return { coin: 8000, hammer: 8, freeze: 8, magic_wand: 8 };
}
export function starterPackNow(): number {
return Date.now() + (cc.fx.GameConfig.GM_INFO.starterPackServerOffset || 0);
}
export function starterPackRemaining(): number {
if (cc.fx.GameConfig.GM_INFO.starterPackPurchased) return 0;
return Math.max(0, Math.ceil(cc.fx.GameConfig.GM_INFO.starter_packTime - starterPackNow() / 1000));
}
export function starterPackTimeText(seconds: number): string {
const value = Math.max(0, Math.floor(seconds));
return [Math.floor(value / 3600), Math.floor(value / 60) % 60, value % 60]
.map(part => String(part).padStart(2, '0')).join(':');
}
export function applyStarterPackStatus(data: any): void {
const info = cc.fx.GameConfig.GM_INFO;
info.starter_packTime = (Number(data.starter_pack) || 0) / 1000;
// A late status response cannot undo a purchase confirmed in this session.
info.starterPackPurchased = info.starterPackPurchased || Number(data.starter_packState) === 1;
if (Number(data.serverTime) > 0) info.starterPackServerOffset = Number(data.serverTime) - Date.now();
}
export function starterPackDay(): string {
// Keep the existing local calendar-day policy, using server-corrected time.
const date = new Date(starterPackNow());
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
}
export function starterPackPopupKey(): string {
return 'Starter_pack_' + cc.fx.GameConfig.GM_INFO.uid;
}
@@ -0,0 +1,10 @@
{
"ver": "1.1.0",
"uuid": "bf11bdec-ae45-4d49-ba7d-d23281e8c91e",
"importer": "typescript",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}
+50 -17
View File
@@ -9,8 +9,8 @@ export default class Utils {
static outTradeNo: string = "";
// static httpip: string = `https://laf.nika4games.com/`; //五彩消消乐
static httpip: string = `https://q6rvwvtnga.sealoshzh.site/`; //消消王者
// static testHttpip: string = `https://sor779u2w8.sealoshzh.site/`; //测试服务器
static testHttpip: string = `https://q6rvwvtnga.sealoshzh.site/`; //消消王者测试服暂替
static testHttpip: string = `https://sor779u2w8.sealoshzh.site/`; //测试服务器
// static testHttpip: string = `https://q6rvwvtnga.sealoshzh.site/`; //消消王者测试服暂替
//#region 安卓支付
/**获取用户信息*/
static getUserInfo(callBack, from?: string) {
@@ -118,6 +118,7 @@ export default class Utils {
// console.error('支付请求超时');
// callBack("请求支付超时");
// }, timeoutDuration);
const orderNumber = res.data.outTradeNo;
//@ts-ignore
wx.requestMidasPaymentGameItem({
signData: res.data.signData,
@@ -126,7 +127,7 @@ export default class Utils {
success(res, errCode) {
// clearTimeout(timeoutId); // 清除超时定时器
//console.log('成功', res, errCode);
callBack(res);
callBack({ ...res, outTradeNo: orderNumber });
},
fail({ errMsg, errCode }) {
// clearTimeout(timeoutId); // 清除超时定时器
@@ -140,6 +141,8 @@ export default class Utils {
callBack(data);
}
})
} else {
callBack({ err: "创建订单失败", errCode: -1, errMsg: res.msg || "创建订单失败,请重试" });
}
});
@@ -147,7 +150,8 @@ export default class Utils {
//#region 安卓获取支付结果
/** 安卓获取支付结果 */
static getPayInfo(callBack) {
static getPayInfo(callBack, order: string = Utils.outTradeNo,
options?: { timeoutMs: number; onProgress?: (response: any) => void }) {
// 延迟时间数组,按照 1 秒 3 次、2 秒 5 次、5 秒 6 次、15 秒 5 次的规则生成
const delays = [
...Array(3).fill(3000),
@@ -156,23 +160,42 @@ export default class Utils {
...Array(5).fill(15000)
];
let attempt = 0; // 轮询次数
let completed = false;
let retryTimer = null;
let deadlineTimer = null;
const finish = (response) => {
if (completed) return;
completed = true;
clearTimeout(retryTimer);
clearTimeout(deadlineTimer);
callBack(response);
};
const timeout = () => {
if (completed) return;
MiniGameSdk.API.showToast(options
? "支付结果尚未确认,请稍后重新领取"
: "网络异常,如付款成功,重进游戏可领取奖励");
finish({ code: 0, data: { pay_state: -1 }, message: '轮询超时' });
};
if (options?.timeoutMs > 0) deadlineTimer = setTimeout(timeout, options.timeoutMs);
const poll = () => {
if (completed) return;
if (attempt >= delays.length) {
MiniGameSdk.API.showToast("网络异常,如付款成功,重进游戏可领取奖励");
callBack({ code: 0, data: { pay_state: -1 }, message: '轮询超时' });
timeout();
return;
}
//console.log("请求uid:", Utils.uid);
//console.log("outTradeNo:", Utils.outTradeNo);
Utils.POST("wx/getPayInfo", { uid: Utils.uid, outTradeNo: Utils.outTradeNo }, res => {
//console.log("查询字符结果:", res);
if (res.code === 1 && (res.data.pay_state === 1 || res.data.pay_state === 2)) {
callBack(res);
Utils.POST("wx/getPayInfo", { uid: Utils.uid, outTradeNo: order }, res => {
if (completed) return;
if (options?.onProgress) options.onProgress(res);
if (res?.code === 1 && (res.data?.pay_state === 1 || res.data?.pay_state === 2)) {
finish(res);
} else {
attempt++;
setTimeout(poll, delays[attempt - 1]);
retryTimer = setTimeout(poll, delays[attempt - 1]);
}
});
};
@@ -193,7 +216,7 @@ export default class Utils {
let orderTemp = Utils.outTradeNo;
if (order) orderTemp = order;
//console.log("告知服务器发货的订单号:", orderTemp);
Utils.POST("wx/getOrderReward", { outTradeNo: orderTemp }, res => {
Utils.POST("wx/getOrderReward", { outTradeNo: orderTemp, uid: cc.fx.GameConfig.GM_INFO.uid }, res => {
//console.log("告知服务器发货:", res);
if (res.code === 1) {
console.log("告知服务器发货成功:", res);
@@ -334,6 +357,16 @@ export default class Utils {
public static POST(url, param: object | any, callback) {
var xhr = cc.loader.getXMLHttpRequest();
xhr.timeout = 5000;//超时时间
let completed = false;
const finish = (response) => {
if (completed) return;
completed = true;
callback(response);
};
const networkFailure = () => finish({ code: 0, data: null, msg: "网络请求失败,请重试" });
xhr.onerror = networkFailure;
xhr.ontimeout = networkFailure;
xhr.onabort = networkFailure;
let dataStr = '';
let isDebug = false;
param.token = cc.fx.GameConfig.GM_INFO.token;
@@ -370,27 +403,27 @@ export default class Utils {
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = function () {
if (xhr && xhr.readyState) {
if (xhr.readyState === 4 && xhr.responseText) {
if (xhr.readyState === 4) {
let response: any = xhr.responseText;
if (xhr.status >= 200 && xhr.status < 300) {
// callback(true, JSON.parse(response));
try {
response = JSON.parse(response);
} catch {
response = { data: "数据有误", code: 0 };
response = { data: null, code: 0, msg: "数据有误" };
}
if (response.code == 0) {
if (response.msg.toString() == "token校验失败") {
if (response.msg === "token校验失败") {
if (MiniGameSdk) {
MiniGameSdk.API.showToast("游戏已更新,请关闭游戏重新进入");
}
}
}
callback(response);
finish(response);
} else {
callback({ data: "网络请求失败,请检查网络连接", code: 0 });
networkFailure();
}
}
}
+18 -15
View File
@@ -5,6 +5,7 @@ import Freeze from "../../prop/Freeze";
import SceneManager from "../../SceneManager";
import { MiniGameSdk } from "../../Sdk/MiniGameSdk";
import Utils from "../Pay/Utils";
import { starterPackReward } from "../Config/StarterPack";
//@ts-ignore
//最大工具类 各种公共方法,以及处理上传,获取后端接口数据
var GameTool = {
@@ -924,7 +925,10 @@ var GameTool = {
},
//商城购买
shopBuy(productId, compensate) {
shopBuy(productId, compensate, orderContext: any = null) {
const starterOrderKey = productId === "starter_pack" && orderContext?.outTradeNo
? "StarterPackGranted_" + cc.fx.GameConfig.GM_INFO.uid + "_" + orderContext.outTradeNo : "";
if (starterOrderKey && cc.fx.StorageMessage.getStorage(starterOrderKey)) return;
let coin = 0;
let price = 0;
let getCoin = 0;
@@ -1174,24 +1178,23 @@ var GameTool = {
}
this.getShopProp(propData3, compensate);
break;
case "starter_pack":
cc.fx.GameTool.changeCoin(3000);
coin = 3000;
case "starter_pack": {
const reward = starterPackReward();
coin = reward.coin;
price = 300;
let propData4 = {
"freeze": 5,
"hammer": 5,
"magic_wand": 5,
"price": price
}
this.getShopProp(propData4, compensate);
cc.fx.GameTool.changeCoin(coin);
this.getShopProp({ freeze: reward.freeze, hammer: reward.hammer,
magic_wand: reward.magic_wand, price }, compensate);
rewardData = [
{ type: "coin", count: coin },
{ type: "freeze", count: 5 },
{ type: "hammer", count: 5 },
{ type: "magic", count: 5 }
]
{ type: "freeze", count: reward.freeze },
{ type: "hammer", count: reward.hammer },
{ type: "magic", count: reward.magic_wand },
];
cc.fx.GameConfig.GM_INFO.starterPackPurchased = true;
if (starterOrderKey) cc.fx.StorageMessage.setStorage(starterOrderKey, true);
break;
}
}