应用程序内购买验证 #

货币化模式和工具非常广泛,包括广告支持、微交易、免费增值、一次性购买以及其间的一切。许多这类解决方案中的一个关键工具是应用程序内购买 (IAP)。借助 IAP,可进行单笔购买,获得解锁、游戏内消费品、会员访问权限订阅等等。

对于最常见的应用程序内购买实现,存在许多现成攻击。其关注点通常包括:

  • 向客户馈送虚假的购买响应,以示成功
  • 多次重播某个有效的购买响应
  • 与另外一个客户端共享购买响应,让多个玩家能够得到单笔购买的回报

对于应用程序内购买,需要有可信的真相来源。Nakama 检查和跟踪购买和购买历史,解决了很多可能的漏洞和难点:

IssueDescription
Fake PurchasesNakama 直接与 Apple、Google 和华为服务连接,检查所有传入的购买收据的有效性。这种验证完全不需要客户端代码,无法被截取和窜改。每次都会核实所有的购买收据,无效的收据会被拒收。
Replay Attacks所有交易都会被记录下来,防止重复提交同一购买令牌或收据。
Receipt Sharing成功的交易会与提交交易的帐户绑定。不同的用户不能提交相同的交易(即使是有效的交易)以试图获得相关的奖励。
Product Mismatches每张经过验证的购买收据都会显示可以将购买绑定到特定产品的数据(例如产品 ID),防止试图使用有效(廉价)购买解锁另一种(昂贵)奖励的攻击。
Single Source of Truth虽然 Nakama 内部保留所有交易的记录,但总是使用远程支付服务提供商进行验证。

无论在哪个平台上,均可以对 AppleGoogle华为购买使用应用程序内购买验证。单个产品和订阅购买均受支持。

通过 Unity IAP 进行的 Apple 和 Google 购买也受支持。

Apple #

Nakama 支持在 iOS 中进行的产品和订阅购买的验证。

Apple 购买收据将被发送到 Apple 进行验证。按照 Apple 的建议,同时使用生产服务器和沙盒服务器来验证收据。

设置 #

为对照 App Store 验证收据,Nakama 需要您应用程序的共享密钥。

  1. 在您应用程序的应用程序内购买管理部分下的 App Store Connect 中设置共享密钥:

    Apple App Store Connect
    Apple App Store Connect

  2. 记录共享密钥,以便在 Nakama 配置中使用:

    Apple App Store Connect 共享密钥
    Apple App Store Connect 共享密钥

  3. 将 Nakama 的iap.apple.shared_password 配置标志的值设置为先前创建的共享密钥的值。

经过验证的购买 #

Nakama 仅支持验证 iOS 7+ 收据。

Apple 收据可包含多笔购买,Nakama 将进行全部验证并将其作为单独的购买记录存储。

Client
1
2
3
4
5
6
string appleReceipt = "<receipt>";
var response = await client.ValidatePurchaseAppleAsync(session, appleReceipt);
foreach (var validatedPurchase in response.ValidatedPurchases)
{
    System.Console.WriteLine("Validated purchase: " + validatedPurchase);
}

请参考提供的运行时购买验证功能的功能参考页面。

Google #

Nakama 支持在 Android 中进行的产品和订阅购买的验证。

设置 #

为对照 Play Store 验证收据,Nakama 需要您的 Google 服务帐户 ClientEmailPrivateKey。获取这些值:

  1. Google API Console 中设置服务帐户

    创建服务帐户
    创建服务帐户

  2. 创建服务帐户后,需要创建密钥:

    创建密钥
    创建密钥

  3. 下载 JSON 文件形式的密钥:

    创建 JSON 密钥
    创建 JSON 密钥

  4. 打开 JSON 文件,提取 ClientEmailPrivateKey 的值。

  5. 将这些值分别设置为 iap.google.client_emailiap.google.private_keyNakama 配置值。

  6. 最后,确保向购买验证 API 授予 Nakama 访问权限。从 Google Play Developer Console,依次进入设置 > API 访问权限

    创建 API 访问权限
    创建 API 访问权限

  7. 您在先前的步骤中创建的服务帐户应在上方列出。授予服务帐户访问 API 的访问权限,确保授予服务帐户对可见性查看财务数据管理订单的访问权限。Nakama 对照 Google Play 验证收据需要这些权限。

    授予访问权限
    授予访问权限

  8. 进入用户和权限,检查正确设定了服务帐户:

    列出有访问权限的用户
    列出有访问权限的用户

验证购买 #

期望的 Google 收据是 Purchase.getOriginalJson() 返回的字符串。请参阅 Google 开发者文档,了解详情。
Client
1
2
3
4
5
6
string googleReceipt = "<receipt>";
var response = await client.ValidatePurchaseGoogleAsync(session, googleReceipt);
foreach (var validatedPurchase in response.ValidatedPurchases)
{
    System.Console.WriteLine("Validated purchase: " + validatedPurchase);
}

请参考提供的运行时购买验证功能的功能参考页面。

华为 #

Nakama 对照其 IAP 验证服务,验证华为购买。按照华为的建议,对照提供的签名检查购买数据的有效性后,才与华为服务联系。如数据因任何原因而无效,将在通过华为验证服务进行验证之前拒绝购买。

验证购买 #

Client
1
2
3
4
5
6
7
string huaweiReceipt = "<receipt>";
string huaweiSignature = "<signature>";
var response = await client.ValidatePurchaseHuaweiAsync(session, huaweiReceipt, huaweiSignature);
foreach (var validatedPurchase in response.ValidatedPurchases)
{
    System.Console.WriteLine("Validated purchase: " + validatedPurchase);
}

请参考提供的运行时购买验证功能的功能参考页面。

Unity IAP #

Unity IAP 受到支持,可与大多数流行的应用商店集成,包括 Apple 和 Google。

Unity IAP 购买收据包含以下信息:

KeyValue
StoreThe name of the store in use, such as GooglePlay or AppleAppStore.
TransactionIDThis transaction’s unique identifier, provided by the store.
PayloadFor Apple, a Base64 encoded App Receipt. For Google, JSON encoded purchase data and a signature.

验证购买 #

Code snippet for this language TypeScript has not been found. Please choose another language to show equivalent examples.

解释验证结果 #

验证结果中会列出经过验证的购买。

因为 Apple 可能会将多笔购买加入单一收据中,因此结果列表中每次经过验证的购买将仅包含经过验证的购买,以及一个表明其是否已经出现过的 boolean 值。如果某笔购买先前已获得 Nakama 验证,“是否出现过”值将是 true,这样开发者即可区分新的购买,防止重播攻击的发生。

对于 Google 和华为,每次验证与单笔购买对应。单笔购买包含在验证响应列表中,也有一个上述“是否出现过”值。

每次经过验证的购买都包含提供商验证响应的有效负载,以备开发者出于任何原因需要它。

如果购买/收据无效,验证因为任何原因失败,或者无法与提供商联系,将返回错误。