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 Developer ドキュメントで詳しく確認できます:

iOS でオファーコードを利用する

オファーコードについて

オファーコードを使うと、特定のユーザーに割引や無料トライアルを提供できます。自動適用される通常のオファーとは異なり、オファーコードはメールキャンペーン、SNS、印刷物などアプリの外で配布されます。ユーザーはApp Storeでコードを入力するか、引き換えURLにアクセスするか、アプリ内ダイアログを通じて利用できます。

オファーコードを設定するには、App Store ConnectでサブスクリプションをのページにあるOpening a subscription, Offer Codes セクションを開きます。オファーコードには3種類あります:

  • 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月にアプリ内課金のプロモコードを廃止しました。オファーコードはより多くの機能を備えた代替手段です:対象者の設定、有効期限の指定、1四半期あたり最大100万コードの発行が可能です。アプリ内課金にプロモコードを使用していた場合は、App Store Connectでオファーコードに移行してください。

従来のプロモコード(アプリのバージョンごとに最大100枚)はサブスクリプションへの無料アクセスを付与するものでした。オファーコードとは異なり、Appleはプロモコードのトランザクションに割引情報を含めず、レシートには定価が送信されていました。そのため、Adaptyはこれらのトランザクションを定価で記録しており、Adaptyアナリティクスとインターネット 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以降、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 はそのような購入を1件保持しておき、登録が完了した時点で即座に配信します。保持されるのは最新の1件のみで、購入を保持するたびにコンソールに警告が出力されます。

プロモート対象のプロダクトにサブスクリプションオファーが含まれている場合、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を持ちます。