312 lines
14 KiB
TypeScript
312 lines
14 KiB
TypeScript
import JiaZai from "../../Script/JiaZai";
|
|
import LoadingCatAnimation from "../../Script/LoadingCatAnimation";
|
|
import Utils from "../../Script/module/Pay/Utils";
|
|
import { MiniGameSdk } from "../../Script/Sdk/MiniGameSdk";
|
|
import { applyStarterPackStatus, starterPackRemaining, starterPackTimeText, starterPackReward } from "../../Script/module/Config/StarterPack";
|
|
|
|
const { ccclass, property } = cc._decorator;
|
|
declare const wx: any;
|
|
|
|
@ccclass
|
|
export default class NewbieGift extends cc.Component {
|
|
// Retain the unused serialized properties in the existing prefab.
|
|
@property(cc.Node) monthCardTime: cc.Node = null;
|
|
@property(cc.Node) monthCardBtn: cc.Node = null;
|
|
@property(cc.Node) monthCardBtn2: cc.Node = null;
|
|
btn_Touch = true;
|
|
private paying = false;
|
|
private polling = false;
|
|
private onShowListener: () => void = null;
|
|
private pendingOrder = "";
|
|
private confirmedOrder = "";
|
|
private orderContext: any = null;
|
|
private offer: any = null;
|
|
|
|
init(first: boolean) {
|
|
this.node.opacity = 255;
|
|
this.offer = cc.fx.GameConfig.GM_INFO.starterPackOffer;
|
|
this.refreshOffer();
|
|
this.closeConfirmBox();
|
|
if (!this.paying) this.closeLoad();
|
|
const title = cc.find("ConfirmBox/title", this.node);
|
|
if (title) title.getComponent(cc.Label).string = "幸运礼包充值";
|
|
// The old Spine/propBg nodes stay disabled. Preserve the authored layout.
|
|
this.unschedule(this.refreshCountdown);
|
|
this.schedule(this.refreshCountdown, 1);
|
|
this.refreshCountdown();
|
|
if (typeof wx !== "undefined" && !this.onShowListener) {
|
|
this.onShowListener = () => this.onShow();
|
|
wx.onShow(this.onShowListener);
|
|
}
|
|
this.onShow();
|
|
}
|
|
|
|
private refreshOffer() {
|
|
const price = Number(this.offer?.priceFen) || 300;
|
|
for (const value of [3, 6, 12, 18, 30]) cc.find("btnContainer/" + value, this.node).active = value * 100 === price;
|
|
const reward = starterPackReward(this.offer?.productId);
|
|
const bundle = cc.assetManager.getBundle("action_bundle");
|
|
bundle.load("img/newbieGift/newbieGiftFont", cc.SpriteAtlas, (error, atlas: cc.SpriteAtlas) => {
|
|
if (error || !cc.isValid(this)) return;
|
|
for (const [path, amount] of [["daoju1/chuiziCount", reward.hammer], ["daoju2/chuiziCount", reward.freeze], ["daoju3/chuiziCount", reward.magic_wand]]) {
|
|
cc.find(String(path), this.node).getComponent(cc.Sprite).spriteFrame = atlas.getSpriteFrame(String(amount));
|
|
}
|
|
const minutes = String(reward.infinite_health / 60);
|
|
const first = cc.find("tiliContainer/tiliCount1", this.node), second = cc.find("tiliContainer/tiliCount2", this.node);
|
|
first.getComponent(cc.Sprite).spriteFrame = atlas.getSpriteFrame(minutes[minutes.length - 2]);
|
|
second.getComponent(cc.Sprite).spriteFrame = atlas.getSpriteFrame(minutes[minutes.length - 1]);
|
|
let hundreds = first.parent.getChildByName("tiliHundreds");
|
|
if (minutes.length === 3 && !hundreds) {
|
|
hundreds = cc.instantiate(first);
|
|
hundreds.name = "tiliHundreds";
|
|
hundreds.x = first.x - (second.x - first.x);
|
|
first.parent.addChild(hundreds);
|
|
}
|
|
if (hundreds) {
|
|
hundreds.active = minutes.length === 3;
|
|
hundreds.getComponent(cc.Sprite).spriteFrame = atlas.getSpriteFrame(minutes[0]);
|
|
}
|
|
});
|
|
cc.assetManager.getBundle("publicUI").load("font", cc.SpriteAtlas, (error, atlas: cc.SpriteAtlas) => {
|
|
if (error || !cc.isValid(this)) return;
|
|
const digits = String(reward.coin);
|
|
cc.find("goldContainer", this.node).children.filter(node => node.name === "New Sprite").forEach((node, index) => {
|
|
node.getComponent(cc.Sprite).spriteFrame = atlas.getSpriteFrame("scoin_" + digits[index]);
|
|
});
|
|
});
|
|
}
|
|
|
|
refreshCountdown() {
|
|
if (!cc.isValid(this)) return;
|
|
const seconds = starterPackRemaining();
|
|
const label = cc.find("timeContainer/time", this.node).getComponent(cc.Label);
|
|
label.string = seconds > 0 ? starterPackTimeText(seconds) : "已结束";
|
|
this.btn_Touch = seconds > 0 && !this.paying;
|
|
cc.find("btnContainer/btn", this.node).getComponent(cc.Button).interactable = this.btn_Touch;
|
|
}
|
|
|
|
onShow() {
|
|
// wx.onShow and the payment callback may arrive together. Only one query
|
|
// chain owns the order; refreshing activity data is not reward delivery.
|
|
if (this.polling) return;
|
|
Utils.getStarter_pack(res => {
|
|
if (res && res.code === 1) applyStarterPackStatus(res.data);
|
|
this.refreshCountdown();
|
|
});
|
|
const order = this.pendingOrder || cc.fx.GameConfig.GM_INFO.iosStarterOrder;
|
|
if (!order) return;
|
|
this.polling = true;
|
|
this.paying = true;
|
|
this.openLoad();
|
|
// Retry only the delivery acknowledgement after payment was confirmed.
|
|
if (this.confirmedOrder === order) {
|
|
this.finishOrder(order);
|
|
return;
|
|
}
|
|
const directPayment = !!this.pendingOrder;
|
|
const version = cc.fx.GameTool.getWechatGameVersion();
|
|
this.logPayment("开始查单", order, {
|
|
channel: directPayment ? "直购" : "iOS客服", version,
|
|
server: version === "开发版" || version === "体验版" ? Utils.testHttpip : Utils.httpip,
|
|
});
|
|
const done = (data) => {
|
|
if (data?.data && /^starter_pack(?:_[2-5])?$/.test(data.data.itemid || data.data.payment_name || "")) {
|
|
this.orderContext = data.data;
|
|
}
|
|
if (directPayment && data?.code === 1 && data.data?.pay_state === 2) {
|
|
this.confirmedOrder = order;
|
|
this.finishOrder(order);
|
|
} else if (!directPayment && data?.code === 1 && /^starter_pack(?:_[2-5])?$/.test(data.data?.payment_name)) {
|
|
// The original customer-service API already completes the order.
|
|
this.completeOrder(order);
|
|
} else if ((directPayment && data?.code === 1 && data.data?.pay_state === 1)
|
|
|| (!directPayment && data?.code === 0 && data.msg === "已经获取到奖励")) {
|
|
// A completed legacy order is not a new grant; clear stale UI state.
|
|
this.completeOrder(order, false);
|
|
} else {
|
|
this.logPayment("等待确认,保留订单供重试", order, {
|
|
code: data?.code, pay_state: data?.data?.pay_state, msg: data?.msg || data?.message,
|
|
});
|
|
this.polling = false;
|
|
this.paying = false;
|
|
this.closeLoad();
|
|
this.refreshCountdown();
|
|
// Keep the order for retry, including after the offer expires.
|
|
this.openConfirmBox();
|
|
}
|
|
};
|
|
if (this.pendingOrder) Utils.getPayInfo(done, order, {
|
|
timeoutMs: 30000,
|
|
onProgress: res => this.logPayment("查单返回", order, {
|
|
code: res?.code, pay_state: res?.data?.pay_state, msg: res?.msg || res?.message,
|
|
}),
|
|
});
|
|
else Utils.getIosPayInfo(order, done);
|
|
}
|
|
|
|
againGet() {
|
|
this.closeConfirmBox();
|
|
this.onShow();
|
|
}
|
|
|
|
buyProduct(event?: cc.Event, customData?: string) {
|
|
if (this.pendingOrder || cc.fx.GameConfig.GM_INFO.iosStarterOrder) {
|
|
this.onShow();
|
|
return;
|
|
}
|
|
this.refreshCountdown();
|
|
if (!this.btn_Touch) return;
|
|
this.paying = true;
|
|
this.refreshCountdown();
|
|
this.openLoad();
|
|
// Fetch the server deadline; purchase eligibility is enforced by this UI.
|
|
Utils.getStarter_pack(res => {
|
|
if (!res || res.code !== 1) {
|
|
this.failPayment("礼包状态获取失败,请重试");
|
|
return;
|
|
}
|
|
applyStarterPackStatus(res.data);
|
|
if (starterPackRemaining() <= 0) {
|
|
this.failPayment("礼包已结束或已购买");
|
|
return;
|
|
}
|
|
let systemType = "Android";
|
|
if (typeof wx !== "undefined" && wx.getSystemInfoSync().platform === "ios") systemType = "ios";
|
|
if (systemType === "ios" && !cc.fx.GameConfig.GM_INFO.iosCanPay) {
|
|
this.iosOldPay();
|
|
return;
|
|
}
|
|
const productId = this.offer?.productId || "starter_pack";
|
|
const price = this.offer?.priceFen || 300;
|
|
Utils.buyProp(productId, 1, price, systemType, productId, result => {
|
|
if (!result || result.err) {
|
|
if (result && result.errCode === 16) {
|
|
this.iosOldPay();
|
|
return;
|
|
}
|
|
this.failPayment("充值失败");
|
|
return;
|
|
}
|
|
if (!result.outTradeNo) {
|
|
this.failPayment("支付订单号缺失,请重进游戏检查补单");
|
|
return;
|
|
}
|
|
this.pendingOrder = result.outTradeNo;
|
|
this.logPayment("微信支付回调成功,等待服务端确认", this.pendingOrder);
|
|
this.onShow();
|
|
}, undefined, this.offer?.round);
|
|
});
|
|
}
|
|
|
|
private finishOrder(order: string) {
|
|
this.logPayment("支付已确认,开始领取确认", order);
|
|
this.paying = true;
|
|
this.openLoad();
|
|
Utils.setPayInfo(res => {
|
|
this.logPayment("领取确认返回", order, { code: res?.code, msg: res?.msg || res?.message });
|
|
this.polling = false;
|
|
if (!res || res.code !== 1) {
|
|
this.paying = false;
|
|
this.openConfirmBox();
|
|
this.refreshCountdown();
|
|
return;
|
|
}
|
|
if (res.starterPackOffer) this.orderContext = res;
|
|
this.completeOrder(order);
|
|
}, order);
|
|
}
|
|
|
|
private completeOrder(order: string, grant = true) {
|
|
if (grant) {
|
|
this.logPayment("开始前端发奖", order);
|
|
// The legacy acknowledgement returns data: "ok", not order metadata.
|
|
const productId = this.orderContext?.itemid || this.orderContext?.payment_name || "starter_pack";
|
|
cc.fx.GameTool.shopBuy(productId, false, { ...this.orderContext, outTradeNo: order });
|
|
this.logPayment("前端发奖调用完成", order);
|
|
MiniGameSdk.API.yinli_Pay(this.orderContext?.starterPackOffer?.priceFen || 300, order, "购买金币道具:" + productId);
|
|
MiniGameSdk.API.showToast("充值成功");
|
|
}
|
|
this.pendingOrder = "";
|
|
this.confirmedOrder = "";
|
|
cc.fx.GameConfig.GM_INFO.iosStarterOrder = "";
|
|
const info = cc.fx.GameConfig.GM_INFO;
|
|
if ((Number(this.orderContext?.starterPackBuyRound) || 1) === (info.starterPackRound || 1)) info.starterPackPurchased = true;
|
|
this.orderContext = null;
|
|
this.polling = false;
|
|
this.paying = false;
|
|
this.buyStarter_pack();
|
|
}
|
|
|
|
private logPayment(stage: string, order: string, details: any = {}) {
|
|
console.log("[新手礼包支付] " + stage, { orderSuffix: String(order).slice(-6), ...details });
|
|
}
|
|
|
|
buyStarter_pack() {
|
|
const canvas = cc.find("Canvas");
|
|
const home = canvas && canvas.getComponent(JiaZai);
|
|
if (home) {
|
|
home.newbieGift = false;
|
|
home.startStarter_pack();
|
|
home.updateCoin();
|
|
}
|
|
const scene = canvas && canvas.getComponent("SceneManager");
|
|
if (scene) scene.refreshJungleRewardDisplay();
|
|
const shopNode = canvas && canvas.getChildByName("shop");
|
|
const shop = shopNode && shopNode.activeInHierarchy && shopNode.getComponent("shop");
|
|
if (shop) shop.refreshJungleRewardDisplay();
|
|
this.closeLoad();
|
|
if (cc.isValid(this)) this.closeStarter_pack();
|
|
}
|
|
|
|
private failPayment(message: string) {
|
|
this.paying = false;
|
|
this.closeLoad();
|
|
this.refreshCountdown();
|
|
MiniGameSdk.API.showToast(message);
|
|
cc.fx.GameTool.shushu_Track("payment_fail", {
|
|
outTradeNo: this.pendingOrder || cc.fx.GameConfig.GM_INFO.iosStarterOrder || "",
|
|
pay_amount: this.offer?.priceFen || 300, payment_name: this.offer?.productId || "starter_pack", payment_num: 1,
|
|
fail_reason: message,
|
|
});
|
|
}
|
|
|
|
iosOldPay() {
|
|
Utils.GoKEFu({ price: this.offer?.priceFen || 300, payment_name: this.offer?.productId || "starter_pack", payment_count: 1,
|
|
starterPackRound: this.offer?.round }, result => {
|
|
this.paying = false;
|
|
this.closeLoad();
|
|
this.refreshCountdown();
|
|
if (result !== "success") {
|
|
cc.fx.GameConfig.GM_INFO.iosStarterOrder = "";
|
|
MiniGameSdk.API.showToast("未能打开支付,请重试");
|
|
}
|
|
});
|
|
}
|
|
|
|
closeStarter_pack() {
|
|
this.node.active = false;
|
|
this.node.emit("starter-pack-closed");
|
|
}
|
|
openLoad() {
|
|
if (cc.isValid(this)) LoadingCatAnimation.play(this.node.getChildByName("Loading"));
|
|
}
|
|
closeLoad() {
|
|
if (cc.isValid(this)) LoadingCatAnimation.stop(this.node.getChildByName("Loading"));
|
|
}
|
|
openConfirmBox() {
|
|
this.closeLoad();
|
|
if (cc.isValid(this)) this.node.getChildByName("ConfirmBox").active = true;
|
|
}
|
|
closeConfirmBox() {
|
|
if (cc.isValid(this)) this.node.getChildByName("ConfirmBox").active = false;
|
|
}
|
|
onDisable() {
|
|
this.unschedule(this.refreshCountdown);
|
|
if (typeof wx !== "undefined" && this.onShowListener) wx.offShow(this.onShowListener);
|
|
this.onShowListener = null;
|
|
}
|
|
onDestroy() {
|
|
this.onDisable();
|
|
}
|
|
}
|