This commit is contained in:
COMPUTER\EDY 2026-08-07 16:06:02 +08:00
parent 76c70cd0d2
commit da57305717
9 changed files with 1475 additions and 73 deletions

View File

@ -323,7 +323,7 @@ export class GameConfig {
vibrateOpen: true, //震动
coinnum: 0, //每局的金币数
paid_user: false, //是否是付费用户
version: "1.0.23", //版本号
version: "1.0.25", //版本号
shushu_DistinctId: "", //数数访客ID
shushu_AccountId: "", //数数账号ID
uid: "", //用户和后端唯一id

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,38 @@
{
"ver": "2.3.7",
"uuid": "a5dbb999-b096-4910-ac02-f080a47a9a73",
"importer": "texture",
"type": "sprite",
"wrapMode": "clamp",
"filterMode": "bilinear",
"premultiplyAlpha": false,
"genMipmaps": false,
"packable": true,
"width": 519,
"height": 168,
"platformSettings": {},
"subMetas": {
"btn_Buy": {
"ver": "1.0.6",
"uuid": "5f7b9cd3-59a0-4a81-87a7-07a6b21c7698",
"importer": "sprite-frame",
"rawTextureUuid": "a5dbb999-b096-4910-ac02-f080a47a9a73",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 0,
"width": 519,
"height": 168,
"rawWidth": 519,
"rawHeight": 168,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"subMetas": {}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

View File

@ -0,0 +1,38 @@
{
"ver": "2.3.7",
"uuid": "2b41eacb-8542-4ff0-aec4-626abc4b5610",
"importer": "texture",
"type": "sprite",
"wrapMode": "clamp",
"filterMode": "bilinear",
"premultiplyAlpha": false,
"genMipmaps": false,
"packable": true,
"width": 994,
"height": 1462,
"platformSettings": {},
"subMetas": {
"kuangt1": {
"ver": "1.0.6",
"uuid": "0fceb2e0-7103-4d02-9e3d-64808e7683fd",
"importer": "sprite-frame",
"rawTextureUuid": "2b41eacb-8542-4ff0-aec4-626abc4b5610",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 0,
"width": 994,
"height": 1462,
"rawWidth": 994,
"rawHeight": 1462,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"subMetas": {}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -7,8 +7,9 @@ export default class JungleTitleShine extends cc.Component {
private sprite: cc.Sprite = null;
private material: cc.Material = null;
private moveDuration: number = 0.85;
private repeatDelay: number = 1.5;
private startDelay: number = 0.25;
// 扫光总周期约 6 秒,与每 2 秒一次的首礼包动画错开。
private repeatDelay: number = 5.15;
private startDelay: number = 3;
private elapsed: number = 0;
private delayRemaining: number = 0;
private startPosition: number = -0.35;

View File

@ -98,6 +98,26 @@ export default class JungleManager extends cc.Component {
private pendingPaymentPrice: number = 0;
private checkingIosOrder: boolean = false;
private entrySource: string = "jump_window";
private unlockPollDelays: number[] = [3000, 3000, 3000, 3000, 6000, 9000, 9000];
private unlockPollMaxAttempts: number = 8;
private unlockPollAttempt: number = 0;
private unlockPollTierId: number = 0;
private unlockPollSession: number = 0;
private unlockPollTimer: any = null;
private unlockRequestTimeout: any = null;
private unlockRequestTimeoutMs: number = 5500;
private isUnlockPolling: boolean = false;
private directPayPollDelays: number[] = [3000, 3000, 3000, 3000, 6000, 9000, 9000];
private directPayPollMaxAttempts: number = 8;
private directPayPollAttempt: number = 0;
private directPayPollSession: number = 0;
private directPayPollTimer: any = null;
private directPayRequestTimeout: any = null;
private directPayRequestTimeoutMs: number = 5500;
private directPayOrderNo: string = "";
private directPayTier: JungleTierConfig = null;
private isDirectPayPolling: boolean = false;
private paymentRetryStage: string = "";
private view: JungleView = null;
private animator: JungleAnimator = null;
@ -162,6 +182,8 @@ export default class JungleManager extends cc.Component {
this.unschedule(this.playFirstCardAttention);
this.clearClaimTimeout();
this.clearPaymentTimeout();
this.stopDirectPayResultPolling(true);
this.stopUnlockStatePolling(true);
this.unregisterWechatOnShow();
}
@ -260,7 +282,6 @@ export default class JungleManager extends cc.Component {
}
private onCardClicked(buttonComponent: cc.Button): void {
console.log("点击礼包档位按钮最外层", buttonComponent);
if (this.isMoving || this.isPurchasing || this.isClaiming
|| this.isUnlockAnimating || !this.activityConfig) {
return;
@ -294,7 +315,6 @@ export default class JungleManager extends cc.Component {
} else if (tier.state === 0) {
this.requestPurchase(tier);
} else {
console.log("点击礼包档位按钮准备请求", buttonComponent);
this.requestClaim(tier);
}
}
@ -343,7 +363,6 @@ export default class JungleManager extends cc.Component {
/** 状态 1 的礼包必须先由后端改成 2成功后才发奖励并播放轨道动画。 */
private requestClaim(tier: JungleTierConfig): void {
this.trackJungleAction("collect_jungle", tier);
console.log("点击礼包档位按钮内里面");
this.isClaiming = true;
this.renderAllCards();
this.openLoad();
@ -358,9 +377,8 @@ export default class JungleManager extends cc.Component {
this.claimTimeout = null;
this.finishClaimFailure("领取请求超时,请稍后重试");
}, 8000);
console.log("点击礼包档位按钮开始请求");
Utils.claimJungleTreasure(tier.id, (response) => {
console.log("点击礼包档位按钮请求结果", response);
if (completed || !cc.isValid(this.node)) {
return;
}
@ -404,7 +422,6 @@ export default class JungleManager extends cc.Component {
this.finishPaymentFailure("支付请求超时,请稍后重试");
// 包含玩家在微信支付面板中的操作时间,不能按普通接口的 8 秒计算。
}, 5 * 60 * 1000);
console.log("准备开始调用 购买礼包接口", this.pendingPaymentPrice);
Utils.buyProp(
tier.productId,
1,
@ -412,52 +429,178 @@ export default class JungleManager extends cc.Component {
systemType,
tier.productId,
(result) => {
console.log("点击礼包档位按钮支付结果", result);
if (!cc.isValid(this.node)) {
console.log("11111点击礼包档位按钮支付结果回调已处理或节点已销毁");
return;
}
callbackReceived = true;
this.clearPaymentTimeout();
if (!result) {
this.finishPaymentFailure("支付拉起失败");
console.log("22222点击礼包档位按钮支付结果回调已处理或节点已销毁");
return;
}
if (result.err) {
if (Number(result.errCode) === 16) {
this.startOldIosPayment(tier);
console.log("33333点击礼包档位按钮支付结果回调已处理或节点已销毁");
return;
}
this.finishPaymentFailure(Number(result.errCode) === -2 ? "已取消支付" : "支付拉起失败");
console.log("44444点击礼包档位按钮支付结果回调已处理或节点已销毁");
return;
}
console.log("55555点击礼包档位按钮支付结果", tier);
this.pollDirectPaymentResult(tier);
},
);
}
private pollDirectPaymentResult(tier: JungleTierConfig): void {
console.log("拿到礼包档位按钮轮询支付结果之后调用档位是否解锁");
Utils.getPayInfo((response) => {
console.log("点击礼包档位按钮轮询支付结果", response);
if (!cc.isValid(this.node)) {
this.directPayOrderNo = String(Utils.outTradeNo || "");
this.directPayTier = tier;
if (!this.directPayOrderNo) {
this.finishPaymentFailure("支付订单号获取失败");
return;
}
this.startDirectPayResultPolling(false);
}
private startDirectPayResultPolling(isManualRetry: boolean): void {
this.stopDirectPayResultPolling(false);
if (!this.directPayOrderNo || !this.directPayTier) {
this.finishPaymentFailure("支付订单信息已失效");
return;
}
this.directPayPollAttempt = 0;
this.isDirectPayPolling = true;
this.isPurchasing = true;
this.paymentRetryStage = "";
this.hideJungleRetryConfirm();
this.requestDirectPayResult(this.directPayPollSession);
}
private requestDirectPayResult(session: number): void {
if (!this.isDirectPayPolling || session !== this.directPayPollSession || !cc.isValid(this.node)) {
return;
}
this.directPayPollAttempt++;
const currentAttempt = this.directPayPollAttempt;
const orderNo = this.directPayOrderNo;
let requestFinished = false;
this.clearDirectPayRequestTimeout();
this.directPayRequestTimeout = setTimeout(() => {
if (requestFinished || session !== this.directPayPollSession) {
return;
}
const payState = Number(response && response.data && response.data.pay_state);
console.log("payState点击礼包档位按钮轮询支付结果", payState);
if (response && response.code === 1 && payState === 2) {
console.log("准备改变礼包状态为可领取", response);
const name = "购买丛林宝藏礼包:" + tier.productId;
MiniGameSdk.API.yinli_Pay(this.pendingPaymentPrice, Utils.outTradeNo, name);
this.refreshAfterPayment(tier.id);
requestFinished = true;
this.directPayRequestTimeout = null;
this.scheduleNextDirectPayPoll(session);
}, this.directPayRequestTimeoutMs);
try {
Utils.POST("wx/getPayInfo", {
uid: cc.fx.GameConfig.GM_INFO.uid || Utils.uid,
outTradeNo: orderNo,
}, (response) => {
if (requestFinished || session !== this.directPayPollSession || !cc.isValid(this.node)) {
return;
}
requestFinished = true;
this.clearDirectPayRequestTimeout();
const payState = Number(response && response.data && response.data.pay_state);
if (response && response.code === 1 && payState === 2) {
this.completeDirectPayResultPolling();
return;
}
if (response && response.code === 1 && payState === 1) {
this.stopDirectPayResultPolling(true);
this.finishPaymentFailure("已取消支付");
return;
}
this.scheduleNextDirectPayPoll(session);
});
} catch (error) {
if (requestFinished || session !== this.directPayPollSession) {
return;
}
this.finishPaymentFailure(payState === 1 ? "已取消支付" : "支付结果获取失败");
});
requestFinished = true;
this.clearDirectPayRequestTimeout();
this.scheduleNextDirectPayPoll(session);
}
}
private scheduleNextDirectPayPoll(session: number): void {
if (!this.isDirectPayPolling || session !== this.directPayPollSession) {
return;
}
if (this.directPayPollAttempt >= this.directPayPollMaxAttempts) {
this.handleDirectPayPollExhausted();
return;
}
const delayIndex = Math.min(this.directPayPollAttempt - 1, this.directPayPollDelays.length - 1);
const delay = this.directPayPollDelays[delayIndex];
this.clearDirectPayPollTimer();
this.directPayPollTimer = setTimeout(() => {
this.directPayPollTimer = null;
this.requestDirectPayResult(session);
}, delay);
}
private completeDirectPayResultPolling(): void {
const tier = this.directPayTier;
const orderNo = this.directPayOrderNo;
const attempts = this.directPayPollAttempt;
this.stopDirectPayResultPolling(true);
this.paymentRetryStage = "";
if (!tier) {
this.finishPaymentFailure("支付成功,但礼包信息已失效");
return;
}
const name = "购买丛林宝藏礼包:" + tier.productId;
MiniGameSdk.API.yinli_Pay(this.pendingPaymentPrice, orderNo, name);
this.refreshAfterPayment(tier.id);
}
private handleDirectPayPollExhausted(): void {
const orderNo = this.directPayOrderNo;
const attempts = this.directPayPollAttempt;
this.stopDirectPayResultPolling(false);
this.paymentRetryStage = "pay_result";
this.isPurchasing = false;
this.closeLoad();
this.renderAllCards();
this.showJungleRetryConfirm();
}
private stopDirectPayResultPolling(clearContext: boolean): void {
this.directPayPollSession++;
this.isDirectPayPolling = false;
this.clearDirectPayPollTimer();
this.clearDirectPayRequestTimeout();
this.directPayPollAttempt = 0;
if (clearContext) {
this.directPayOrderNo = "";
this.directPayTier = null;
}
}
private clearDirectPayPollTimer(): void {
if (this.directPayPollTimer) {
clearTimeout(this.directPayPollTimer);
this.directPayPollTimer = null;
}
}
private clearDirectPayRequestTimeout(): void {
if (this.directPayRequestTimeout) {
clearTimeout(this.directPayRequestTimeout);
this.directPayRequestTimeout = null;
}
}
/** iOS 旧支付:跳转客服,回到小游戏时由 wx.onShow 查询订单结果。 */
@ -538,62 +681,231 @@ export default class JungleManager extends cc.Component {
}
private refreshAfterPayment(tierId: number): void {
let completed = false;
this.clearPaymentTimeout();
this.paymentTimeout = setTimeout(() => {
if (completed) {
return;
}
completed = true;
this.paymentTimeout = null;
this.finishPaymentFailure("支付成功,礼包状态刷新超时,请重新进入活动");
}, 8000);
this.startUnlockStatePolling(tierId, false);
}
const requestUnlockedState = () => {
if (completed || !cc.isValid(this.node)) {
/** ConfirmBox 重试按钮事件:按失败阶段继续查询支付结果或礼包解锁状态。 */
public retryJungleUnlock(): void {
if (this.paymentRetryStage === "pay_result") {
if (!this.directPayOrderNo || !this.directPayTier) {
this.hideJungleRetryConfirm();
this.showToast("支付订单信息已失效");
return;
}
if (this.isDirectPayPolling) {
return;
}
this.hideJungleRetryConfirm();
this.isPurchasing = true;
this.renderAllCards();
this.openLoad();
this.startDirectPayResultPolling(true);
return;
}
if (this.unlockPollTierId <= 0) {
this.hideJungleRetryConfirm();
this.showToast("没有需要重试的礼包");
return;
}
if (this.isUnlockPolling) {
return;
}
this.hideJungleRetryConfirm();
this.isPurchasing = true;
this.renderAllCards();
this.openLoad();
this.startUnlockStatePolling(this.unlockPollTierId, true);
}
private startUnlockStatePolling(tierId: number, isManualRetry: boolean): void {
this.clearPaymentTimeout();
this.stopUnlockStatePolling(false);
if (tierId <= 0) {
this.finishPaymentFailure("支付成功,但礼包档位信息无效");
return;
}
this.unlockPollTierId = tierId;
this.unlockPollAttempt = 0;
this.isUnlockPolling = true;
this.isPurchasing = true;
this.paymentRetryStage = "";
this.hideJungleRetryConfirm();
const totalAttempts = this.unlockPollMaxAttempts;
this.requestUnlockState(this.unlockPollSession);
}
private requestUnlockState(session: number): void {
if (!this.isUnlockPolling || session !== this.unlockPollSession || !cc.isValid(this.node)) {
return;
}
this.unlockPollAttempt++;
const currentAttempt = this.unlockPollAttempt;
const totalAttempts = this.unlockPollMaxAttempts;
const tierId = this.unlockPollTierId;
let requestFinished = false;
this.clearUnlockRequestTimeout();
this.unlockRequestTimeout = setTimeout(() => {
if (requestFinished || session !== this.unlockPollSession) {
return;
}
requestFinished = true;
this.unlockRequestTimeout = null;
this.scheduleNextUnlockPoll(session);
}, this.unlockRequestTimeoutMs);
try {
Utils.getJungleTreasure((response) => {
if (completed || !cc.isValid(this.node)) {
if (requestFinished || session !== this.unlockPollSession || !cc.isValid(this.node)) {
return;
}
requestFinished = true;
this.clearUnlockRequestTimeout();
const data = response && response.code === 1 ? response.data : null;
const states = data && data.tierStates;
const refreshedState = Array.isArray(states) && tierId > 0
? Number(states[tierId - 1])
: -1;
// 微信支付回调会先把订单改为成功,再写玩家的活动解锁状态。
// 订单成功后第一次读取可能仍为 0因此在原有 8 秒超时内继续轮询。
if (!data || !data.config || !Array.isArray(states)
|| (tierId > 0 && refreshedState !== 1 && refreshedState !== 2)) {
this.scheduleOnce(requestUnlockedState, 0.4);
if (data && data.config && Array.isArray(states)
&& (refreshedState === 1 || refreshedState === 2)) {
this.completeUnlockStatePolling(tierId, refreshedState, data, states);
return;
}
completed = true;
this.clearPaymentTimeout();
this.isPurchasing = false;
this.publishServerState(data);
const refreshed = this.setServerData(data.config, states);
if (refreshed && refreshedState === 1) {
this.playTierUnlockAnimation(tierId);
}
if (!refreshed) {
this.closeLoad();
this.renderAllCards();
this.showToast("支付成功,礼包状态刷新失败,请重新进入活动");
return;
}
// setServerData 已将付费档位从“3元”重新渲染为“领取”完成后再关闭 Loading。
this.closeLoad();
this.showToast("支付成功,礼包已解锁");
this.scheduleNextUnlockPoll(session);
});
};
requestUnlockedState();
} catch (error) {
if (requestFinished || session !== this.unlockPollSession) {
return;
}
requestFinished = true;
this.clearUnlockRequestTimeout();
this.scheduleNextUnlockPoll(session);
}
}
private scheduleNextUnlockPoll(session: number): void {
if (!this.isUnlockPolling || session !== this.unlockPollSession) {
return;
}
const totalAttempts = this.unlockPollMaxAttempts;
if (this.unlockPollAttempt >= totalAttempts) {
this.handleUnlockPollExhausted();
return;
}
const delayIndex = Math.min(this.unlockPollAttempt - 1, this.unlockPollDelays.length - 1);
const delay = this.unlockPollDelays[delayIndex];
this.clearUnlockPollTimer();
this.unlockPollTimer = setTimeout(() => {
this.unlockPollTimer = null;
this.requestUnlockState(session);
}, delay);
}
private completeUnlockStatePolling(
tierId: number,
refreshedState: number,
data: any,
states: JungleTierState[],
): void {
this.stopUnlockStatePolling(true);
this.paymentRetryStage = "";
this.isPurchasing = false;
this.publishServerState(data);
const refreshed = this.setServerData(data.config, states);
if (refreshed && refreshedState === 1) {
this.playTierUnlockAnimation(tierId);
}
if (!refreshed) {
this.closeLoad();
this.renderAllCards();
this.showToast("支付成功,礼包状态刷新失败,请重新进入活动");
return;
}
this.hideJungleRetryConfirm();
// setServerData 已将付费档位从“几元”重新渲染为“领取”,完成后再关闭 Loading。
this.closeLoad();
this.showToast("支付成功,礼包已解锁");
}
private handleUnlockPollExhausted(): void {
const tierId = this.unlockPollTierId;
const attempts = this.unlockPollAttempt;
this.stopUnlockStatePolling(false);
this.paymentRetryStage = "unlock_state";
this.isPurchasing = false;
this.closeLoad();
this.renderAllCards();
this.showJungleRetryConfirm();
}
private showJungleRetryConfirm(): void {
const confirmBox = this.node.getChildByName("ConfirmBox");
if (!confirmBox) {
this.showToast("网络异常,请检查网络后重新进入活动");
return;
}
confirmBox.zIndex = 100;
if (confirmBox.parent) {
confirmBox.setSiblingIndex(confirmBox.parent.childrenCount - 1);
}
confirmBox.active = true;
}
private hideJungleRetryConfirm(): void {
const confirmBox = this.node.getChildByName("ConfirmBox");
if (confirmBox) {
confirmBox.active = false;
}
}
private stopUnlockStatePolling(clearTierId: boolean): void {
this.unlockPollSession++;
this.isUnlockPolling = false;
this.clearUnlockPollTimer();
this.clearUnlockRequestTimeout();
this.unlockPollAttempt = 0;
if (clearTierId) {
this.unlockPollTierId = 0;
}
}
private clearUnlockPollTimer(): void {
if (this.unlockPollTimer) {
clearTimeout(this.unlockPollTimer);
this.unlockPollTimer = null;
}
}
private clearUnlockRequestTimeout(): void {
if (this.unlockRequestTimeout) {
clearTimeout(this.unlockRequestTimeout);
this.unlockRequestTimeout = null;
}
}
private finishPaymentFailure(message: string): void {
this.stopDirectPayResultPolling(true);
this.stopUnlockStatePolling(true);
this.paymentRetryStage = "";
this.hideJungleRetryConfirm();
this.clearPaymentTimeout();
this.closeLoad();
this.isPurchasing = false;
@ -652,6 +964,7 @@ export default class JungleManager extends cc.Component {
}
private showToast(message: string): void {
console.log("显示提示:", message);
if (MiniGameSdk && MiniGameSdk.API && MiniGameSdk.API.showToast) {
MiniGameSdk.API.showToast(message);
}

View File

@ -741,7 +741,7 @@
"_contentSize": {
"__type__": "cc.Size",
"width": 1080,
"height": 4300
"height": 4600
},
"_anchorPoint": {
"__type__": "cc.Vec2",