在移动应用中通过 Kotlin Multiplatform SDK 进行购买

在移动应用中展示付费墙是向用户提供高级内容或服务访问权限的关键步骤。然而,仅当 Adapty 负责渲染界面时——即使用流程或旧版付费墙编辑工具构建的付费墙——展示付费墙本身才能自动支持购买操作。

如果你在自己的代码中渲染界面,则必须调用一个名为 .makePurchase() 的独立方法来完成购买并解锁相应内容。该方法是用户与付费墙交互并完成交易的入口。

如果你的付费墙中某个产品存在有效的促销活动,Adapty 会在用户购买时自动应用该优惠。

Warning

请注意,只有在 Adapty 渲染页面时,新用户优惠才会自动应用。

在其他情况下,您需要在 iOS 上验证用户是否具备新用户优惠资格。跳过此步骤可能导致您的应用在发布时被拒绝,并可能对有资格享受新用户优惠的用户收取全价。

请确保您已完成初始配置,不要跳过任何步骤。否则我们将无法验证购买。

发起购买

Note

Adapty 是否负责渲染您的页面? 对于流程或付费墙编辑工具付费墙,购买会自动处理——您可以跳过此步骤。

想要分步指导? 请查看快速入门指南,获取包含完整背景说明的端到端实现指引。


Adapty.makePurchase(product = product).onSuccess { purchaseResult ->
    when (purchaseResult) {
        is AdaptyPurchaseResult.Success -> {
            val profile = purchaseResult.profile
            if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive == true) {
                // Grant access to the paid features
            }
        }
        is AdaptyPurchaseResult.UserCanceled -> {
            // Handle the case where the user canceled the purchase
        }
        is AdaptyPurchaseResult.Pending -> {
            // Handle deferred purchases (e.g., the user will pay offline with cash)
        }
    }
}.onError { error ->
    // Handle the error
}

请求参数:

参数是否必填描述
Product必填从付费墙中获取的 AdaptyPaywallProduct 对象。

响应参数:

参数描述
Profile

请求成功后,响应中包含此对象。AdaptyProfile 对象提供了用户在应用内的访问等级、订阅及非订阅购买的完整信息。

请检查访问等级状态,以确认用户是否具有所需的应用访问权限。

Warning

注意: 如果你使用的 Apple StoreKit 版本低于 v2.0,且 Adapty SDK 版本低于 v2.9.0,则需要提供 Apple App Store 共享密钥。该方法目前已被 Apple 弃用。

购买时更换订阅

当用户选择新订阅而非续订当前订阅时,具体行为取决于所使用的应用商店。对于 Google Play,订阅不会自动更新,你需要按照以下说明在移动应用代码中手动处理切换逻辑。

要在 Android 中将订阅替换为另一个订阅,请在调用 .makePurchase() 方法时传入额外参数:


val subscriptionUpdateParams = AdaptyAndroidSubscriptionUpdateParameters(
    oldSubVendorProductId = "old_subscription_product_id",
    replacementMode = AdaptyAndroidSubscriptionUpdateReplacementMode.CHARGE_FULL_PRICE
)

val purchaseParams = AdaptyPurchaseParameters.Builder()
    .setSubscriptionUpdateParams(subscriptionUpdateParams)
    .build()

Adapty.makePurchase(
    product = product,
    parameters = purchaseParams
).onSuccess { purchaseResult ->
    when (purchaseResult) {
        is AdaptyPurchaseResult.Success -> {
            val profile = purchaseResult.profile
            // successful cross-grade
        }
        is AdaptyPurchaseResult.UserCanceled -> {
            // user canceled the purchase flow
        }
        is AdaptyPurchaseResult.Pending -> {
            // the purchase has not been finished yet, e.g. user will pay offline by cash
        }
    }
}.onError { error ->
    // Handle the error
}

附加请求参数:

参数是否必填描述
parameters可选通过 AdaptyPurchaseParameters 传入的 AdaptyAndroidSubscriptionUpdateParameters 对象。

您可以在 Google 开发者文档中了解更多关于订阅和替换模式的信息:

在 iOS 中兑换优惠码

关于优惠码

优惠码允许你向特定用户提供折扣或免费试用。与自动应用的常规优惠不同,优惠码通过应用外渠道分发——例如电子邮件营销、社交媒体或印刷材料。用户可通过在 App Store 中输入代码、访问兑换链接或使用应用内对话框来兑换。

要设置优惠码,请在 App Store Connect 中打开某个订阅,并进入其 Offer Codes 部分。你可以创建三种类型的优惠码:

  • Free — 订阅在设定时长内免费,下次续费恢复原价。
  • Pay as you go — 用户在设定时长内每个计费周期以折扣价付费,之后订阅恢复原价续费。
  • Pay up front — 用户为整个优惠期限支付一次性折扣价,之后订阅恢复原价续费。

你无需将优惠码添加到 Adapty。Apple 会在优惠期间为每笔交易打上优惠码类别标签,包括初次兑换和所有后续折扣续费。Adapty 检测到该标签后,会将每笔交易记录为优惠类别 offer_code。优惠期结束、订阅以原价续费后,该标签将不再存在。你可以在 Adapty 看板中通过 Offer Code 优惠类型筛选分析数据。

收入差异排查

如果你发现 Adapty 中某笔优惠码交易显示的是产品原价而非折扣价,请在 App Store Connect 中核查以下内容:

  • 优惠码已为用户可兑换的所有地区配置了正确的定价。
  • 已为用户所在的特定国家或地区设置了优惠价格。Apple 在交易中发送的是地区价格。如果该优惠未配置对应地区的价格,Apple 可能会发送产品原价。

你可以在 Adapty 看板中通过 Offer Code 优惠类型和 Offer Discount Type 筛选条件来过滤和核查优惠码交易。

旧版促销码(已弃用)

Warning

Apple 于 2026 年 3 月弃用了应用内购买的促销码。优惠码以更强大的功能取而代之:可配置的使用资格、过期日期,以及每季度最多 100 万个代码。如果你此前使用促销码进行应用内购买,请在 App Store Connect 中迁移至优惠码。

旧版促销码(每个应用每个版本限 100 个)可免费授予订阅访问权限。与优惠码不同,Apple 不会在促销码交易中包含折扣信息——它在收据中发送的是产品原价。因此,Adapty 会以原价记录这些交易,导致 Adapty 分析数据与 App Store Connect 之间出现收入差异。

如果你看到历史交易以原价记录但实际上应为免费,这些很可能来自旧版促销码。由于这些代码现已弃用,请迁移至优惠码以确保收入数据准确。

在您的应用中显示代码兑换界面:

Adapty.presentCodeRedemptionSheet()
    .onSuccess {
        // code redemption sheet presented successfully
    }
    .onError { error ->
        // handle the error
    }
Danger

根据我们的观察,部分应用中的优惠码兑换界面可能无法可靠运行。我们建议将用户直接重定向至 App Store。

为此,您需要打开以下格式的 URL: https://apps.apple.com/redeem?ctx=offercodes&id={apple_app_id}&code={code}

管理预付方案 (Android)

如果您的应用用户可以购买预付方案(例如,购买数月的非续订订阅),您可以为预付方案启用待处理交易。


Adapty.activate(
    AdaptyConfig.Builder("PUBLIC_SDK_KEY")
        .withGoogleEnablePendingPrepaidPlans(true)
        .build()
).onSuccess {
    // successful activation
}.onError { error ->
    // handle the error
}

来自 App Store 的推广应用内购买

Info

你的应用从 SDK 4.1 版本起支持接收 App Store 的推广应用内购买,且需要 iOS 16.4 或更高版本。低于 iOS 16.4 时,监听器不会触发,推广购买会自动完成。这是一个仅限 iOS 的功能:在 Android 上监听器同样不会触发,且 makePromotedPurchase 会返回 AdaptyErrorCode.DEVELOPER_ERROR。

当用户从 App Store 产品页面发起购买,且交易转移到您的应用时,SDK 会通过 OnPromotedPurchaseListener 将产品传递给您。完成购买由您的应用负责:将产品传入 makePromotedPurchase。由于您可以控制购买发起的时机,您可以在购买开始前展示自己的界面。

要支持推广购买,请注册监听器并在其中完成购买:


Adapty.setOnPromotedPurchaseListener(OnPromotedPurchaseListener { product ->
    scope.launch {
        Adapty.makePromotedPurchase(product)
            .onSuccess { result -> /* process the purchase result */ }
            .onError { error -> /* handle the error */ }
    }
})
Warning

如果未注册监听器,促销购买将永远无法完成:App Store 会将产品传递给你的应用并等待响应。向 setOnPromotedPurchaseListener 传入 null 同样会导致促销购买无法正常工作。

在应用启动时,紧接着 Adapty.activate 之后注册监听器。促销购买通常会冷启动应用,因此往往在你完成注册之前就已到达 SDK。SDK 会暂存一个此类购买,并在你注册后立即将其投递,但只保留最新的一个,并在每次暂存购买时写入控制台警告。

如果推广产品附带订阅优惠,SDK 会在购买时自动应用该优惠。该优惠从 App Store 购买意图中读取,在 iOS 18.0 及更高版本上可获取此信息;在 iOS 16.4–17.x 上,购买将按原价进行。

makePromotedPurchase 不接受任何购买参数——推广产品来自 App Store 而非付费墙,因此不携带任何付费墙上下文。它返回与 makePurchase 相同的 AdaptyPurchaseResult。

AdaptyPromotedProduct 包含 vendorProductId、localizedTitle、localizedDescription、price、regionCode、isFamilyShareable,以及一个 AdaptyProductSubscription 类型的 subscription。