包含此页的版本:
不含此页的版本:
应用收据存储在设备的本地存储中,可以按如下方式读取:
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);
});
}
下面的示例类演示了如何访问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;
}
}
}
当购买被批准或拒绝时,您的商店正常ProcessPurchase或OnPurchaseFailed监听器方法被调用。
有时,消耗品“购买前询问”购买项目不会显示在 App 收据中,在这种情况下,您无法使用该收据来验证它们。但是,iOS 提供了包含所有购买的交易收据,包括购买前询问。访问给定的最新交易收据字符串Product用IAppleExtensions.
注意:交易收据不适用于 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 允许您通过应用程序的产品页面推广游戏内购买。与传统的 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,请遵循以下清单:
构建桌面 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 测试用户帐户登录名。然后,您将能够针对沙盒环境进行测试购买。