利用now.gg支付模块,可以在您的Unity游戏里实现应用内购买。
使用now.gg支付模块实现应用内购买需要:
now.gg支付Unity模块以Unity的包文件形式 nowgg-payments-login.unitypackage
被引入。
将模块添加到您的Unity工程中:
nowgg-payments-login.unitypackage
。导入所有模块文件后,工程中将创建一个名为’NowGGSdk‘的文件夹。您可以在Assets文件夹的根目录下找到该文件夹。
注意:请不要修改NowGGSdk文件夹,因为其中包含与now.gg支付相关的所有资源。
此操作将使用Unity外部依赖关系管理器(External Dependency Manager)下载所有依赖,并将其添加到 Assets/Plugins/Android
目录中。
添加所需依赖项:
导入now.gg支付模块并添加依赖项后,您可以按照此章节操作在您的应用程序/游戏中集成now.gg支付。
要运行now.gg IAP服务,需要使用now.gg平台。Unity IAP(或任何其他 IAP 服务)仅在非now.gg平台上运行时才能进行初始化。
检查当前运行的平台,在你的项目中添加以下代码,以便您的应用程序在now.gg平台上运行时Unity IAP不会被激活:
public void Start() { if (NowGG.Sdk.NowGGPaymentsSdkManager.IsNowGGIapAvailable()) return; // 您的 Unity IAP 代码... }
以下章节说明了now.gg IAP函数的实现,您可以从Unity的应用/游戏中调用这些函数。
首先创建一个包含now.gg IAP实现的类,并将其附加到一个可用于初始化应用内购买的游戏对象。
此步骤将允许您在应用/游戏中添加应用内购买产品,并初始化模块。比如,我们在以下代码中添加了两个IAP 可消耗型产品(IAP consumable products),它们分别是带有 productId
的 ‘coin1’ 和 ‘coin2’。我们还添加了一个带有 productId
的月包(‘monthlyPack’)的订阅(subscription)。
同样地,如果您在nowStudio中还添加了其他产品和订阅(具有对应的 productId
),您也可以将它们添加进来。
在初始化支付时,必须将唯一用户ID (IN_GAME_ID
)传递给now.gg支付模块,如以下示例代码所示:
public void Start() { // 如果运行在 Now.gg 平台,仅初始化 Now.gg IAP if (!NowGG.Sdk.NowGGPaymentsSdkManager.IsNowGGIapAvailable()) return; // 可消耗产品请参考 NowGGProductBuilder.Instance.AddProduct("coin1", ProductType.Consumable); NowGGProductBuilder.Instance.AddProduct("coin2", ProductType.Consumable); // 订阅请参考 NowGGProductBuilder.Instance.AddProduct("monthlyPack", ProductType.Subscription); NowGGPaymentsSdkManager.Instance.OnInitSuccess += OnInitSuccess; NowGGPaymentsSdkManager.Instance.OnInitFailed += OnInitFailed; NowGGPaymentsSdkManager.Instance.OnPurchaseCompleted += OnPurchaseProduct; NowGGPaymentsSdkManager.Instance.OnPurchaseFailed += OnPurchaseFailed; NowGGPaymentsSdkManager.Instance.InitializeIap(PAYMENT_ID, IN_GAME_ID); }
说明:
NowGGProductBuilder
类中。NowGGPaymentsSdkManager
类的 InitializeIap
函数被调用,以使用 PAYMENT_ID
初始始化支付模块。IN_GAME_ID
是您用户的唯一标识符。
IN_GAME_ID
对每个用户都是唯一的。
IN_GAME_ID
。IN_GAME_ID
进行支付测试,请将其添加为nowStudio内部测试员。PAYMENT_ID
是您应用的唯一标识符。
在成功初始化之后,您可以使用 productId
获取产品详情。
要获取产品详情,请参考以下实现:
private void OnInitSuccess() { Debug.Log($"IAP init success"); Product coin1 = NowGGPaymentsSdkManager.Instance.GetProductWithID("coin1"); // 现在你可以使用 productId 获取产品详情 // 可消耗型 string price = coin1.price; string currencyCode = coin1.priceCurrencyCode; // 订阅 Product monthlyPack = NowGGPaymentsSdkManager.Instance.GetProductWithID("monthlyPack"); string monthlyPackSubscriptionPeriod = monthlyPack.subscriptionPeriod; } private void OnInitFailed(string reason) { Debug.Log($"IAP init failed {reason}"); }
参考资料:
获取了产品详情之后,您可以发起产品购买。为此,您需要调用如下所示的 PurchaseProduct()
函数:
public void PurchaseProduct(string productId, string developerPayload=null) { NowGGPaymentsSdkManager.Instance.PurchaseProduct(productId, developerPayload); }
参考资料:
以下方法展示了如何将购买的权利分配给用户:
我们提供了两种方式实现购买的消费:
我们提供了两种方式用于确认购买的订阅:
private PurchaseProcessingResult OnPurchaseProduct(PurchasedProduct purchasedProduct) { string orderId = purchasedProduct.orderId; string purchaseToken = purchasedProduct.purchaseToken; string developerPayload = purchasedProduct.developerPayload; // 用户购买了一个可消耗产品。 if (String.Equals(purchasedProduct.productId, "coin1", StringComparison.Ordinal)) { Debug.Log(string.Format("OnPurchaseProduct: PASS. Product: '{0}'", purchasedProduct.productId)); // 可消耗产品被成功购买, 为玩家添加100的游戏内货币。 // coin += 100; } else if (String.Equals(purchasedProduct.productId, "coin2", StringComparison.Ordinal)) { Debug.Log(string.Format("OnPurchaseProduct: PASS. Product: '{0}'", purchasedProduct.productId)); // 可消耗产品被成功购买, 为玩家添加200的游戏内货币。 // coin += 200; } else if (String.Equals(purchasedProduct.productId, "monthlyPack", StringComparison.Ordinal)) { Debug.Log(string.Format("OnPurchaseProduct: PASS. Product: '{0}'", purchasedProduct.productId)); Debug.Log("Subscription: " + purchasedProduct.subscriptionStatus + " " + purchasedProduct.subscriptionPeriod + " " + purchasedProduct.expiryTimeMillis + " " + purchasedProduct.subscriptionPurchaseDateMillis); if (purchasedProduct.subscriptionStatus == "ACTIVE" && purchaseProduct.isAcknowledged == false) { // 订阅被成功购买。将订阅的权利交付给玩家。 // 根据购买订阅的状态,计费周期,到期时间更新UI。 // 返回 PurchaseProcessingResult.Complete 以确认购买已被确认(订阅) } } else { Debug.Log(string.Format("OnPurchaseProduct: FAIL. Unrecognized product: '{0}'", purchasedProduct.productId)); } // 返回一个标志,表明该产品是否已收到,或者应用程序是否需要在下次启动时提醒此购买。 // 返回 PurchaseProcessingResult.Pending,如果你希望在下一次启动应用程序/游戏时提醒此次购买。 // 返回 PurchaseProcessingResult.Complete,代表可消耗型产品(consumable products)的购买已被消费(consumed),或者订阅(subscriptions)已被确认(acknowledged ),并且已将购买的权利交付给用户。 // 确保您已将购买的权利交付给用户。 return PurchaseProcessingResult.Complete; }
注意:
OnPurchaseProduct
中返回 PurchaseProcessingResult.Pending
。
参考资料:
purchaseToken
。orderId
。
对于有后端服务器的应用,应使用 consumePurchase
API 进行服务端的购买消费。
在验证购买之后,您应该将其标记为已消费。
购买的实现包括:
将购买的产品分配给用户。
通知now.gg该产品已被消费。
以下示例代码展示了使用 consumePurchase
API 的相关请求。
import requests url = "https://cloud-api.bluestacks.cn/v2/order/consumePurchase" payload = 'purchaseToken=nowgg-_purchase_token' headers = { 'Authorization': 'payment_api_key_here', 'Content-Type': 'application/x-www-form-urlencoded' } response = requests.request("POST", url, headers=headers, data=payload) print(response.text)
参考资料
consumePurchase
API之前,请确保将购买的产品分配给用户。Payments API Key
)可以在nowStudio的证书章节找到。 更多信息。acknowledgePurchase
API应被用于服务器端的订阅型产品的确认。
在验证购买之后,您应该将其标记为已确认。
下列示例代码展示了使用 acknowledgePurchase
API的相关请求。
import requests url = "https://cloud-api.bluestacks.cn/v2/seller/order/acknowledgepurchase" payload = 'purchaseToken=nowgg-_purchase_token' headers = { 'Authorization': 'payment_api_key_here', 'Content-Type': 'application/x-www-form-urlencoded' } response = requests.request("POST", url, headers=headers, data=payload) print(response.text)
参考资料
Payments API Key
)可以在nowStudio的证书章节找到。更多信息。如果您想在您的后端服务器上处理购买,或者您需要根据您的实现机制使用另一种方法来完成购买,您的应用应从 OnPurchaseProduct
返回 PurchaseProcessingResult.Pending
。
要完成购买流程,您可以使用 ConfirmPendingPurchase
方法通知 now.gg IAP服务,告知应用已经记录下该购买行为。
public void ConfirmPendingPurchase(string purchasetoken, ProductType productType) { if (productType == ProductType.Consumable) { ConsumeProduct(purchasetoken); } else { AcknowledgePurchase(purchasetoken); } }
参考资料:
要想完成购买流程,且使用您的应用后端服务器对购买进行授权,则需要调用以下API:
如果您需要查询待处理的购买,您可以调用 NowGGPaymentsSdkManager
类的 QueryPendingPurchases
函数。此函数将会查询所有待处理的购买,并调用 OnPurchaseProduct
回调函数,返回待处理的购买。
NowGGPaymentsSdkManager.Instance.QueryPendingPurchases();
参考资料:OnPurchaseProduct.
如果您想要获取其他产品以供购买,或是想要刷新现有产品的详细信息/元数据,那么您可以使用 FetchAdditionalProducts
函数,如下所示:
var newProducts = new System.Collections.Generic.Dictionary<string, ProductType>(); newProducts.Add("coin2", ProductType.Consumable); newProducts.Add("coin3", ProductType.Consumable); NowGGPaymentsSdkManager.Instance.FetchAdditionalProducts(newProducts, () => { //在获取了其他产品后, 用户就可以购买它们。 Debug.Log($"Successfully fetched additional products"); Product coin1 = NowGGPaymentsSdkManager.Instance.GetProductWithID("coin1"); string price = coin1.price; string currencyCode = coin1.priceCurrencyCode; }, reason => { Debug.Log($"Fetching additional products failed: {reason}"); });
购买可能会由于各种各样的原因而导致失败,其中包括:
您可以通过参考下面的代码实现来对失败的购买进行调查和处理:
public void OnPurchaseFailed(int errorCode, string errorMessage) { Debug.Log($"OnPurchaseFailed: errorCode: {errorCode} and msg: {errorMessage}"); }
注意:
OnPurchaseFailed
函数相关的响应码 参考此处。本章节说明了 API 规范,以便您为我们提供 SubscriptionStatusCallback
API,用于发送订阅状态的更新。
下述是相关工作流程:
参考资料:Subscription Status Callback API。
您可以使用一下两种方法之一来验证购买:
验证购买的第一种方法是使用 verifyPurchase API。您可以使用此 API 向我们的后端服务器验证购买。
为验证购买, 从您应用的后端服务器用 purchaseToken
作为参数,调用 verifyPurchase API,如以下示例请求代码所示:
curl --location 'https://cloud-api.bluestacks.cn/v2/seller/order/verifyPurchase' \ --header 'Authorization: <payment_api_key_here>' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'purchaseToken=<nowgg_purchase_token>'
import requests url = "https://cloud-api.bluestacks.cn/v2/seller/order/verifyPurchase" payload = 'purchaseToken=<nowgg_purchase_token>' headers = { 'Authorization': '<payment_api_key_here>', 'Content-Type': 'application/x-www-form-urlencoded' } response = requests.request("POST", url, headers=headers, data=payload) print(response.text)
您可以在本地验证购买,也可以使用后端服务器,但是我们建议您使用后端服务器来验证购买。
您可以按照 此处列出的步骤 来生成公钥。
以下代码分别演示了在本地和使用后端服务器进行购买验证。您可以参考 演示应用程序工程(Demo project)了解更多详情。
private PurchaseProcessingResult OnPurchaseProduct(PurchasedProduct purchasedProduct) { // 使用此示例代码进行本地验证 bool isValidPurchase = PurchaseVerification.Instance.VerifyPurchaseLocally( BASE_64_ENCODED_PUBLIC_KEY, purchasedProduct.originalJson, purchasedProduct.signature); // 我们推荐使用您的后端服务器进行验证 // 您需要发送签名和原始数据到您的后端服务器进行验证。 PurchaseVerification.Instance.VerifyValidSignatureOnBackend( purchasedProduct.originalJson, purchasedProduct.signature); // 用户买了可消耗型的产品 if (String.Equals(purchasedProduct.productId, "coin1", StringComparison.Ordinal)) { Debug.Log(string.Format("OnPurchaseProduct: PASS. Product: '{0}'", purchasedProduct.productId)); // 可消耗产品被成功购买, 为玩家添加100的游戏内货币。 // coin += 100; } else if (String.Equals(purchasedProduct.productId, "coin2", StringComparison.Ordinal)) { Debug.Log(string.Format("OnPurchaseProduct: PASS. Product: '{0}'", purchasedProduct.productId)); // 可消耗产品被成功购买, 为玩家添加200的游戏内货币。 // coin += 200; } else { Debug.Log(string.Format("OnPurchaseProduct: FAIL. Unrecognized product: '{0}'", purchasedProduct.productId)); } return PurchaseProcessingResult.Complete; }
下载包 包含了一个实现示例,用于使用后端服务器验证购买,您也可以参考编写自己的实现。
示例实现包括:
我们在下载包中提供了一个示例实现,用于本地验证购买的情况,您可以使用提供的示例来编写自己的实现。
在示例实现中:
PurchaseVerification
类的 VerifyPurchaseLocally
函数。