You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity内置IAP中如何仅在真实购买时触发营收分析?

解决Unity IAP中仅真实购买触发Fabric营收分析的问题

嘿,我来帮你搞定这个问题~ 你遇到的核心痛点是ProcessPurchase()在首次订阅和恢复购买时都会被调用,导致如果直接在这里加Fabric代码,会把恢复的情况也误统计成新购买,对吧?下面给你拆解解决方案,以及纠正代码放置的位置:

首先:如何区分「真实购买」和「恢复购买」

Unity IAP本身没有直接提供区分两者的字段,但我们可以通过两种可靠的方式来判断:

方式1:用恢复标记跟踪(简单直接)

在调用恢复购买的方法时,设置一个全局标记,ProcessPurchase()里根据这个标记判断是否是恢复场景:

private bool _isRestoringPurchases = false;

// 你的恢复购买触发方法
public void TriggerRestorePurchases() {
    _isRestoringPurchases = true;
    UnityPurchasing.Instance.RestoreTransactions((success) => {
        _isRestoringPurchases = false;
        // 恢复完成后的提示逻辑,比如弹窗告知用户
    });
}

方式2:用交易ID去重(更通用,覆盖自动恢复场景)

有些平台可能会自动恢复购买(比如用户重装APP后),这种情况不会走你手动调用的恢复方法,这时候跟踪已处理的交易ID更靠谱:

private HashSet<string> _processedTransactionIds = new HashSet<string>();

void Awake() {
    // 从本地加载之前处理过的交易ID,避免重启APP后重复统计
    string savedIds = PlayerPrefs.GetString("ProcessedTransactions", "");
    if (!string.IsNullOrEmpty(savedIds)) {
        foreach (string id in savedIds.Split(',')) {
            _processedTransactionIds.Add(id);
        }
    }
}

然后:Fabric API的正确放置位置

不管用哪种区分方式,你都需要把Fabric的营收统计代码放在确认是首次真实购买的分支里,而不是直接放在ProcessPurchase()的开头。结合你的代码片段,修改后的示例如下:

结合恢复标记的完整代码

public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args) {
    bool validPurchase = true;
    
    // 第一步:先做你的收据验证逻辑(比如校验receipt合法性)
    if (/* 你的收据验证不通过 */) {
        validPurchase = false;
    }

    if (validPurchase) {
        // 第二步:判断是否是真实购买,而非恢复
        if (!_isRestoringPurchases) {
            // 这里才是调用Fabric API的正确位置!
            // 比如:Fabric.Analytics.LogPurchase(
            //     args.purchasedProduct.definition.id, 
            //     args.purchasedProduct.metadata.localizedPrice,
            //     args.purchasedProduct.metadata.isoCurrencyCode
            // );
            Debug.Log("已记录真实购买到Fabric");
        } else {
            Debug.Log("恢复购买,跳过Fabric统计");
        }

        // 第三步:处理商品逻辑(比如解锁功能、激活订阅)
        UnlockPremiumContent(args.purchasedProduct);
    }

    return PurchaseProcessingResult.Complete;
}

结合交易ID去重的完整代码

public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args) {
    bool validPurchase = true;
    
    // 第一步:收据验证
    if (/* 验证失败 */) {
        validPurchase = false;
    }

    if (validPurchase) {
        string transactionId = args.purchasedProduct.transactionID;
        // 第二步:判断该交易是否已经处理过
        if (!_processedTransactionIds.Contains(transactionId)) {
            // 真实购买,调用Fabric API
            // Fabric.Analytics.LogPurchase(...);
            Debug.Log("已记录真实购买到Fabric");
            
            // 保存交易ID到本地,避免重复统计
            _processedTransactionIds.Add(transactionId);
            PlayerPrefs.SetString("ProcessedTransactions", string.Join(",", _processedTransactionIds));
            PlayerPrefs.Save();
        } else {
            Debug.Log("该交易已处理(恢复购买),跳过Fabric统计");
        }

        // 第三步:处理商品逻辑
        UnlockPremiumContent(args.purchasedProduct);
    }

    return PurchaseProcessingResult.Complete;
}

为什么你原来的代码位置不对?

如果直接在ProcessPurchase()里不加判断就调用Fabric,会把「恢复购买」也当成「新购买」统计,导致你的营收数据虚高,无法准确反映真实的用户付费行为——毕竟恢复购买只是找回已有的权益,不是产生新的营收。

内容的提问来源于stack exchange,提问作者Tengku Fathullah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:13:29