Version: 6000.3
语言: 中文
店铺指南
通用 Windows 平台

iOS 和 Mac 应用商店

扩展功能

阅读应用程序收据

应用收据存储在设备的本地存储中,可以按如下方式读取:

var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
string receipt = builder.Configure<IAppleConfiguration>().appReceipt;

检查付款限制

应用内购买可能会在设备的设置中受到限制,可以按如下方式检查:

var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
bool canMakePayments = builder.Configure<IAppleConfiguration>().canMakePayments;

恢复事务

在 Apple 平台上,用户必须输入密码才能检索以前的交易,因此您的应用程序必须为用户提供一个按钮,让他们这样做。在此过程中,ProcessPurchase你的方法IStoreListener将对用户已经拥有的任何项目调用。

/// <summary>
/// Your IStoreListener implementation of OnInitialized.
/// </summary>
public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
{
    extensions.GetExtension<IAppleExtensions> ().RestoreTransactions (result => {
        if (result) {
            // This does not mean anything was restored,
            // merely that the restoration process succeeded.
        } else {
            // Restoration failed.
        }
    });
}

刷新应用收据

Apple 提供了一种从其服务器获取新 App Receipt 的机制,通常在当前没有缓存在本地存储中时使用;SKReceiptRefreshRequest 中。

请注意,这将提示用户输入密码。

Unity IAP 使此方法可用,如下所示:

/// <summary>
/// Your IStoreListener implementation of OnInitialized.
/// </summary>
public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
{
    extensions.GetExtension<IAppleExtensions> ().RefreshAppReceipt (receipt => {
        // This handler is invoked if the request is successful.
        // Receipt will be the latest app receipt.
        Console.WriteLine(receipt);
    },
    () => {
        // This handler will be invoked if the request fails,
        // such as if the network is unavailable or the user
        // enters the wrong password.
    });
}

要求购买

iOS 8 引入了一项名为“购买前询问”的新家长控制功能。

要求购买推迟购买以供家长批准。当这种情况发生时,Unity IAPUnity In App Purchase
的缩写 术语表
向应用发送通知,如下所示:

/// This is called when Unity IAP has finished initialising.
public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
{
    extensions.GetExtension<IAppleExtensions>().RegisterPurchaseDeferredListener(product => {
        Console.WriteLine(product.definition.id);
    });
}

在 Sandbox App Store 中启用“购买前询问”模拟

下面的示例类演示了如何访问IAppleExtensions要在沙盒应用商店中启用“购买前询问”模拟,请执行以下作:

using UnityEngine;
using UnityEngine.Purchasing;

public class AppleSimulateAskToBuy : MonoBehaviour {
    public void SetSimulateAskToBuy(bool shouldSimulateAskToBuy) {
        if (Application.platform == RuntimePlatform.IPhonePlayer) {
            IAppleExtensions extensions = IAPButton.IAPButtonStoreManager.Instance.ExtensionProvider.GetExtension<IAppleExtensions>();
            extensions.simulateAskToBuy = shouldSimulateAskToBuy;
        }
    }
}

当购买被批准或拒绝时,您的商店正常ProcessPurchaseOnPurchaseFailed监听器方法被调用。

交易收据

有时,消耗品“购买前询问”购买项目不会显示在 App 收据中,在这种情况下,您无法使用该收据来验证它们。但是,iOS 提供了包含所有购买的交易收据,包括购买前询问。访问给定的最新交易收据字符串ProductIAppleExtensions.

注意:交易收据不适用于 Mac 版本。在 Mac 版本上请求事务收据会导致一个空字符串。

#if UNITY_PURCHASING

using System;
using UnityEngine;
using UnityEngine.Purchasing;

public class AskToBuy : MonoBehaviour, IStoreListener
{
    // Unity IAP objects
    private IStoreController m_Controller;
    private IAppleExtensions m_AppleExtensions;

    public AskToBuy ()
    {
        var builder = ConfigurationBuilder.Instance (StandardPurchasingModule.Instance ());
        builder.AddProduct ("100_gold_coins", ProductType.Consumable, new IDs {
            { "100_gold_coins_google", GooglePlay.Name },
            { "100_gold_coins_mac", MacAppStore.Name }
        });

        UnityPurchasing.Initialize (this, builder);
    }

    /// <summary>
    /// This will be called when Unity IAP has finished initialising.
    /// </summary>
    public void OnInitialized (IStoreController controller, IExtensionProvider extensions)
    {
        m_Controller = controller;
        m_AppleExtensions = extensions.GetExtension<IAppleExtensions> ();

        // On Apple platforms we need to handle deferred purchases caused by Apple's Ask to Buy feature.
        // On non-Apple platforms this will have no effect; OnDeferred will never be called.
        m_AppleExtensions.RegisterPurchaseDeferredListener (OnDeferred);
    }

    /// <summary>
    /// This will be called when a purchase completes.
    /// </summary>
    public PurchaseProcessingResult ProcessPurchase (PurchaseEventArgs e)
    {
        if (Application.platform == RuntimePlatform.IPhonePlayer ||
            Application.platform == RuntimePlatform.tvOS) {
            string transactionReceipt = m_AppleExtensions.GetTransactionReceiptForProduct (e.purchasedProduct);
            Console.WriteLine (transactionReceipt);
            // Send transaction receipt to server for validation
        }    
        return PurchaseProcessingResult.Complete;
    }

    /// <summary>
    /// Called when Unity IAP encounters an unrecoverable initialization error.
    ///
    /// Note that this will not be called if Internet is unavailable; Unity IAP
    /// will attempt initialization until it becomes available.
    /// </summary>
    public void OnInitializeFailed (InitializationFailureReason error)
    {
    }

    /// <summary>
    /// Called when a purchase fails.
    /// </summary>
    public void OnPurchaseFailed (Product i, PurchaseFailureReason p)
    {
    }

    /// <summary>
    /// iOS Specific.
    /// This is called as part of Apple's 'Ask to buy' functionality,
    /// when a purchase is requested by a minor and referred to a parent
    /// for approval.
    ///
    /// When the purchase is approved or rejected, the normal purchase events
    /// will fire.
    /// </summary>
    /// <param name="item">Item.</param>
    private void OnDeferred (Product item)
    {
        Debug.Log ("Purchase deferred: " + item.definition.id);
    }
}

#endif // UNITY_PURCHASING

与应用收据不同,您无法在本地验证交易收据。相反,您必须将收据字符串发送到远程服务器进行验证。如果您已使用远程服务器来验证应用收据,请将事务收据发送到同一 Apple 端点,以接收 JSON 响应。

JSON 响应示例:

{
    "receipt": {
        "original_purchase_date_pst": "2017-11-15 15:25:20 America/Los_Angeles",
        "purchase_date_ms": "1510788320209",
        "unique_identifier": "0ea7808637555b2c633eb07aa1cb0894c821a6f9",
        "original_transaction_id": "1000000352597239",
        "bvrs": "0",
        "transaction_id": "1000000352597239",
        "quantity": "1",
        "unique_vendor_identifier": "01B57C2E-9E91-42FF-9B0D-4983175D6694",
        "item_id": "1141751870",
        "original_purchase_date": "2017-11-15 23:25:20 Etc/GMT",
        "product_id": "100.gold.coins",
        "purchase_date": "2017-11-15 23:25:20 Etc/GMT",
        "is_trial_period": "false",
        "purchase_date_pst": "2017-11-15 15:25:20 America/Los_Angeles",
        "bid": "com.unity3d.unityiap.demo",
        "original_purchase_date_ms": "1510788320209"
    },
    "status": 0
}

拦截 Apple 促销购买

Apple 允许您通过应用程序的产品页面推广游戏内购买。与传统的 App 内购买不同,Apple 促销购买直接从 iOS 和 Apple tvOS 上的 App Store 启动。然后,App Store 会启动你的 App 以完成交易,或者提示用户下载 App(如果尚未安装)。

IAppleConfiguration SetApplePromotionalPurchaseInterceptorcallback 方法拦截 Apple 促销购买。使用此回调呈现家长门,发送analyticsUnity 的缩写 Analytics
术语表
事件,或在将购买的商品发送给 Apple 之前执行其他功能。回调使用Product用户尝试购买的。您必须调用IAppleExtensions.ContinuePromotionalPurchases()以继续促销购买。这将启动任何排队付款。

如果您未设置回传,促销购买会立即通过并调用ProcessPurchase结果。

注意:在其他平台上调用这些 API 没有效果。

private IAppleExtensions m_AppleExtensions;

public void Awake() {
    var module = StandardPurchasingModule.Instance();
    var builder = ConfigurationBuilder.Instance(module);
        // On iOS and tvOS we can intercept promotional purchases that come directly from
        // the App Store.
        // On other platforms this will have no effect; OnPromotionalPurchase will never be
        // called.
    builder.Configure<IAppleConfiguration>().
     SetApplePromotionalPurchaseInterceptorCallback(OnPromotionalPurchase);
    Debug.Log("Setting Apple promotional purchase interceptor callback");
}

public void OnInitialized(IStoreController controller, IExtensionProvider extensions) {
    m_AppleExtensions = extensions.GetExtension<IAppleExtensions>();
    foreach (var item in controller.products.all) {
        if (item.availableToPurchase) {                
            // Set all these products to be visible in the user's App Store
            m_AppleExtensions.SetStorePromotionVisibility(item, AppleStorePromotionVisibility.Show);
        }
    }
}

private void OnPromotionalPurchase(Product item) {
    Debug.Log("Attempted promotional purchase: " + item.definition.id);
    // Promotional purchase has been detected. 
    // Handle this event by, e.g. presenting a parental gate.
    // Here, for demonstration purposes only, we will wait five seconds before continuing 
    // the purchase.
    StartCoroutine(ContinuePromotionalPurchases());
}

private IEnumerator ContinuePromotionalPurchases() {
    Debug.Log("Continuing promotional purchases in 5 seconds");
    yield return new WaitForSeconds(5);
    Debug.Log("Continuing promotional purchases now");
    m_AppleExtensions.ContinuePromotionalPurchases (); // iOS and tvOS only
}

测试

要在 Apple Store 上进行测试,您必须使用 iTunes Connect 测试帐户,该帐户可以在 iTunes Connect 中创建。

在 iOS 设备或笔记本电脑上注销 App Store,启动您的应用程序,当您尝试购买或恢复交易时,系统会提示您登录。

如果您收到初始化失败,原因为NoProductsAvailable,请遵循以下清单:

  • iTunes Connect 产品标识符必须与提供给 Unity IAP 的产品标识符完全匹配
  • 必须在 iTunes Connect 中为您的应用程序启用应用内购买
  • 产品必须在 iTunes Connect 中获准销售
  • 新创建的 iTunes Connect 产品可能需要数小时才能购买
  • 您必须同意最新的 iTunes Connect 开发者协议并拥有有效的银行详细信息

Mac 应用商店

构建桌面 Mac 版本时,您必须选择Mac App Store validation在 Unity 的构建设置中。

构建应用后,必须使用捆绑标识符和版本字符串更新其 info.plist 文件。右键单击.app文件,然后单击show package contents,找到info.plist文件并更新CFBundleIdentifier字符串添加到应用程序的捆绑标识符。

然后,您必须对应用程序进行签名、打包和安装。您需要从 OSX 终端运行以下命令:

codesign -f --deep -s "3rd Party Mac Developer Application: " your.app/Contents/Plugins/unitypurchasing.bundle
codesign -f --deep -s "3rd Party Mac Developer Application: " your.app
productbuild --component your.app /Applications --sign "3rd Party Mac Developer Installer: " your.pkg

要对捆绑包进行签名,您可能首先需要删除 Contents.meta 文件(如果存在):your.app/Contents/Plugins/unitypurchasing.bundle/Contents.meta

为了正确安装包,您必须在运行新创建的包之前删除未打包的.app文件。

然后,您必须从应用程序文件夹启动您的应用程序。第一次执行此作时,系统会提示您输入 iTunes 帐户详细信息,为此您应该输入 iTunes Connect 测试用户帐户登录名。然后,您将能够针对沙盒环境进行测试购买。

店铺指南
通用 Windows 平台