Version: 2017.1
Android 应用内购 (IAP) 商店的跨店安装问题
通用 Windows 平台

iOS App Store 和 Mac App Store

Extended Functionality

读取应用程序收据

应用程序收据 (App Receipt) 存储在设备的本地存储器中,可以按如下方式读取:

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

检查是否有支付限制

应用内购 (IAP) 可能在设备设置中受到限制,可以按以下方式检查是否存在限制:

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

Restoring Transactions

在 Apple 平台上,用户必须输入密码才能检索以前的交易,因此您的应用程序必须为用户提供一个按钮来输入密码。此过程中将会针对用户已拥有的任何商品调用 IStoreListenerProcessPurchase 方法。

/// <summary>
/// IStoreListener 对 OnInitialized 的实现。
/// </summary>
public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
{
    extensions.GetExtension<IAppleExtensions> ().RestoreTransactions (result => {
        if (result) {
            // 这并不意味着已恢复任何对象,
            // 只表示恢复过程成功了。
        } else {
            //恢复操作已失败。
        }
    });
}

刷新应用程序收据

Apple provides a mechanism to fetch a new App Receipt from their servers, typically used when no receipt is currently cached in local storage; SKReceiptRefreshRequest.

请注意,这种情况下将提示用户输入密码。

Unity IAP 按如下形式提供此方法:

/// <summary>
/// IStoreListener 对 OnInitialized 的实现。
/// </summary>
public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
{
    extensions.GetExtension<IAppleExtensions> ().RefreshAppReceipt (receipt => {
        // 如果请求成功,则调用此处理程序。
        //收据将是最新的应用程序收据。
        Console.WriteLine(receipt);
    },
    () => {
        //如果请求失败
        //(例如网络不可用或用户输入错误的密码),
        //则会调用此处理程序。
    });
}

购买前先询问

iOS 8 introduced a new parental control feature; Ask to Buy

Ask to buy allows an In App Purchase to be deferred to a parent for approval. When this occurs, Unity IAP will send your App a notification if it registers to be notified as follows.

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

If and when the purchase is approved or rejected, the normal ProcessPurchase/OnPurchaseFailed methods of your store listener will be invoked.

测试

要在 Apple 商店中进行测试,必须使用 iTunes Connect 测试帐户(可以在 iTunes Connect 中创建该帐户)。

Sign out of the app store on the iOS device or laptop, launch your application and you will be prompted to log in when you attempt either a purchase or to restore transactions.

If you receive an initialization failure with a reason of NoProductsAvailable, follow this checklist:

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

Mac App Store

When building a desktop Mac build you must select Mac App Store validation within Unity’s build settings.

Once you have built your App, you must update its info.plist file with your bundle identifier and version strings. Right click on the .app file and click show package contents, locate the info.plist file and update the CFBundleIdentifier string to your application’s bundle identifier.

随后,必须对应用程序进行签名、打包和安装。您需要从 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 文件,然后再运行新创建的程序包。

随后,必须从 Applications 文件夹启动应用程序。首次启动应用程序时,系统会提示输入您的 iTunes 帐户详细信息,此时应输入 iTunes Connect 测试用户帐户的登录信息。然后,您便可以在沙盒环境中进行购买测试。

Android 应用内购 (IAP) 商店的跨店安装问题
通用 Windows 平台