1. 2023 年 8 月 2 日以降、すべての新規アプリでは Billing Library バージョン 5 以降を使用する必要があります。また既存のアプリのアップデートについては、2023 年 11 月 1 日より Billing Library バージョン 5 以降の使用が必須となります。詳細
2. Android 14 以降をターゲットとするアプリの場合は、PBL 5.2.1 または PBL 6.0.1 以降に更新する必要があります。

代替の課金システムのアプリ内統合のガイダンス(韓国のみ)

このガイドでは、代替の課金システムの API をアプリに統合する方法について説明します。

Play Billing Library のセットアップ

Android アプリに Play Billing Library の依存関係を追加します。代替の課金システムの API を使用するには、バージョン 5.2 以降を使用する必要があります。以前のバージョンから移行する必要がある場合は、移行ガイドの手順に沿って代替の課金システムを実装してください。

Google Play に接続する

統合プロセスの最初のステップは、Google Play 請求サービスの統合ガイドに記載のステップと同じですが、BillingClient の初期化の際にいくつかの違いがあります。

  • enableAlternativeBilling という新しいメソッドを呼び出して、課金方法の選択肢をユーザーに提供することを示す必要があります。
  • AlternativeBillingListener を登録して、ユーザーが代替の課金システムを選択するケースを処理する必要があります。

次の例は、これらの変更を行った BillingClient の初期化方法を示しています。

Kotlin

val purchasesUpdatedListener =
   PurchasesUpdatedListener { billingResult, purchases ->
       // Handle new Google Play purchase.
   }

val alternativeBillingListener =
   AlternativeBillingListener { alternateChoiceDetails ->
       // Handle alternative billing choice.
   }

var billingClient = BillingClient.newBuilder(context)
   .setListener(purchasesUpdatedListener)
   .enablePendingPurchases()
   .enableAlternativeBilling(alternativeBillingListener)
   .build()

Java

private PurchasesUpdatedListener purchasesUpdatedListener = new PurchasesUpdatedListener() {
    @Override
    public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
        // Handle new Google Play purchase.
    }
};

private AlternativeBillingListener alternativeBillingListener = new AlternativeBillingListener() {
    @Override
    public void userSelectedAlternativeBilling(
        AlternativeChoiceDetails alternateChoiceDetails) {
        // Handle new Google Play purchase.
    }
};

private BillingClient billingClient = BillingClient.newBuilder(context)
    .setListener(purchasesUpdatedListener)
    .enablePendingPurchases()
    .enableAlternativeBilling(alternativeBillingListener)
    .build();

BillingClient を初期化したら、統合ガイドの説明のとおりに Google Play への接続を確立する必要があります。

購入可能な商品を表示する

Google Play の課金システムの統合と同様に、購入可能な商品をユーザーに表示できます。ユーザーが購入可能な商品を確認し、購入する商品を選択したら、次のセクションで説明するように、ユーザー選択型決済のフローを開始します。

ユーザー選択型決済のフローを開始する

launchBillingFlow() を呼び出して、ユーザー選択型決済のフローを開始します。これは、Google Play 課金システムの統合を使用した購入フローの開始と同じように機能します。ProductDetails のインスタンスと、商品とユーザーが獲得したい特典に対応する offerToken を指定します。ユーザーが Google Play の課金システムを選択すると、この情報を使用して購入フローが続行されます。

デベロッパーが launchBillingFlow を呼び出すと、Google Play の課金システムが次のロジックを実行します。

  • システムが、ユーザーの Google Play の国が韓国であるかどうかを確認します。ユーザーの Google Play の国が韓国の場合、Google Play は、BillingClient の設定に基づいて代替の課金システムが有効になっているどうかを確認します。

    • 代替の課金システムが有効になっている場合は、購入フローで新しい UX が表示されます。
    • 代替の課金システムが有効になっていない場合、購入フローには、ユーザー選択なしで標準の Google Play 課金システムの UX が表示されます。
  • ユーザーの Google Play の国が韓国以外の場合、購入フローには、標準の Google Play の課金システムの UX がユーザー選択なしで表示されます。

ユーザーの Play の国が韓国 ユーザーの Play の国が韓国以外
BillingClient のセットアップ中に enableAlternativeBilling が呼び出された 新しい UX が表示される 標準の Google Play の課金システムの UX が表示される
BillingClient のセットアップ中に enableAlternativeBilling が呼び出されなかった 標準の Google Play の課金システムの UX が表示される 標準の Google Play の課金システムの UX が表示される

ユーザー選択を処理する

残りの購入フローの処理方法は、ユーザーが Google Play の課金システムを選択するか、代替の課金システムを選択するかによって異なります。

ユーザーが代替の課金システムを選択した場合

ユーザーが代替の課金システムを選択すると、Google Play は AlternativeBillingListener を呼び出し、代替の課金システムでの購入フローを開始する必要があることをアプリに通知します。具体的には、userSelectedAlternativeBilling() メソッドが呼び出されます。

AlternativeChoiceDetails オブジェクトで指定される外部取引トークンは、ユーザーが代替の課金システムのフローに入ることを選択する署名を表します。このトークンは、バックエンド統合ガイドの説明のとおり、この選択から発生する取引を報告するために使用します。

AlternativeBillingListener は、次のアクションを実行する必要があります。

  • ユーザーが購入する商品を取得して、代替の課金システムの購入フローで提示できるようにします。
  • 外部取引トークンとして受け取った文字列を収集し、バックエンドに送信して永続化します。これは、後でユーザーがこの購入を完了した場合に Google Play に外部取引を報告するために使用されます。
  • デベロッパーの代替の購入のフローを開始します。

ユーザーがデベロッパーの代替の課金システムを使用して購入を完了した場合、バックエンドから Google Play Developer API を呼び出して、取引を Google Play に報告する必要があります。その際には、externalTransactionToken とその他の取引詳細を提供します。詳しくは、バックエンド統合ガイドをご覧ください。

次の例は、AlternativeBillingListener の実装方法を示しています。

Kotlin

private val alternativeBillingListener =
    AlternativeBillingListener { alternativeChoiceDetails ->
        // Get the products being purchased by the user.
        val products = alternativeChoiceDetails.products

        // Send external transaction token to developer backend server
        // this devBackend object is for demonstration purposes,
        // developers can implement this step however best fits their
        // app to backend communication.
        devBackend.sendExternalTransactionStarted(
            alternativeChoiceDetails.externalTransactionToken,
            user
        )

        // Launch alternative billing
        // ...
        // The developer backend handles reporting the transaction
        // to Google Play's backend once the alternative billing
        // purchase is completed.
    }

Java

private AlternativeBillingListener alternativeBillingListener = new AlternativeBillingListener() {
    @Override
    public void userSelectedAlternativeBilling(
           AlternativeChoiceDetails alternateChoiceDetails) {
       // Get the products being purchased by the user.
       List<Product> products =
              alternativeChoiceDetails.getProducts();

       // Send external transaction token to developer backend server
       // this devBackend object is for demonstration purposes,
       // developers can implement this step however best fits their
       // app to backend communication.
       devBackend.sendExternalTransactionStarted(
              alternateChoiceDetails.getExternalTransactionToken(),
              user
       );

       // Launch alternative billing
       // ...
       // The developer backend handles reporting the transaction
       // to Google Play's backend once the alternative billing
       // purchase is completed.
    }
};

ユーザーが Google Play の課金システムを選択した場合

ユーザーが Google Play の課金システムを選択した場合は、Google Play で購入を続行します。

  • Google Play の課金システムで新しいアプリ内購入を処理する方法の詳細については、ライブラリ統合ガイドの購入の処理をご覧ください。
  • 定期購入に関するその他のガイダンスについては、定期購入管理ガイドの新しい定期購入をご覧ください。

定期購入の変更を処理する

代替の課金システムを使用しているデベロッパーは、ユーザーの選択に応じて、購入を Google Play の課金システムで処理するか、externalTransactionId で報告する必要があります。ユーザー選択のフローで処理された既存の定期購入に対する変更は、有効期限まで同じ課金システムで行うことができます。

このセクションでは、定期購入の変更に関する一般的なシナリオを処理する方法について説明します。

アップグレードとダウングレードのフロー

アップグレードとダウングレードのフローは、定期購入を Google Play の課金システムと代替の課金システムのどちらで処理したかによって、異なる処理を行う必要があります。

代替の課金システムで購入した定期購入

ユーザー選択後にデベロッパーの代替の課金システムで購入した定期購入については、アップグレードまたはダウングレードをリクエストするユーザーは、再度ユーザー選択を行うことなくデベロッパーの代替の課金システムに進む必要があります。

これを行うには、ユーザーがアップグレードまたはダウングレードをリクエストしたときに launchBillingFlow を呼び出します。パラメータで SubscriptionUpdateParams オブジェクトを指定する代わりに、setOriginalExternalTransactionId を使用して、元の購入の外部取引 ID を指定します。元の購入のユーザー選択がアップグレードとダウングレードで変わっていなければ、ユーザー選択画面は表示されません。この場合、launchBillingFlow を呼び出すと、コールバックから取得できる取引の新しい外部取引トークンが生成されます。

Kotlin

// The external transaction ID from the current
// alternative billing subscription.
val externalTransactionId = //... ;

val billingFlowParams = BillingFlowParams.newBuilder()
    .setProductDetailsParamsList(
        listOf(
            BillingFlowParams.ProductDetailsParams.newBuilder()
                // Fetched via queryProductDetailsAsync.
                .setProductDetails(productDetailsNewPlan)
                // offerIdToken can be found in
                // ProductDetails=>SubscriptionOfferDetails.
                .setOfferToken(offerTokenNewPlan)
                .build()
        )
    )
    .setSubscriptionUpdateParams(
        BillingFlowParams.SubscriptionUpdateParams.newBuilder()
            .setOriginalExternalTransactionId(externalTransactionId)
            .build()

val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)

// When the user selects the alternative billing flow,
// the AlternativeBillingListener is triggered.

Java

// The external transaction ID from the current
// alternative billing subscription.
String externalTransactionId = //... ;

BillingFlowParams billingFlowParams =
        BillingFlowParams.newBuilder()
            .setProductDetailsParamsList(
                ImmutableList.of(
                    ProductDetailsParams.newBuilder()
                        // Fetched via queryProductDetailsAsync.
                        .setProductDetails(productDetailsNewPlan)
                        // offerIdToken can be found in
                        // ProductDetails=>SubscriptionOfferDetails
                        .setOfferToken(offerTokenNewPlan)
                    .build()
                )
            )
            .setSubscriptionUpdateParams(
                SubscriptionUpdateParams.newBuilder()
                    .setOriginalExternalTransactionId(externalTransactionId)
                    .build()
            )
            .build();

BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);

// When the user selects the alternative billing flow,
// the AlternativeBillingListener is triggered.

代替の課金システムでアップグレードまたはダウングレードが完了したら、新しい定期購入に関する上記の呼び出しで取得した外部取引トークンを使用して新しい取引を報告する必要があります。

Google Play の課金システムで購入した定期購入

同様に、ユーザー選択後に Google Play の課金システムで現在の定期購入を購入したユーザーには、Google Play の課金システムでのアップグレードまたはダウングレードのフローが表示されます。Google Play の課金システムでアップグレードまたはダウングレードの購入フローを開始する手順は以下のとおりです。

  1. 新しいプランを対象に選択した特典の offerToken を特定します。

    Kotlin

    val offerTokenNewPlan = productDetailsNewPlan
                 .getSubscriptionOfferDetails(selectedOfferIndex)
                 .getOfferToken()
    

    Java

    String offerTokenNewPlan = productDetailsNewPlan
                         .getSubscriptionOfferDetails(selectedOfferIndex)
                         .getOfferToken();
    
  2. 既存の定期購入の購入トークンなど、新しい購入を処理するために正しい情報を Google Play の課金システムに送信します。

    Kotlin

    val billingFlowParams =
        BillingFlowParams.newBuilder().setProductDetailsParamsList(
            listOf(
                BillingFlowParams.ProductDetailsParams.newBuilder()
                    .setProductDetails(productDetailsNewPlan)
                    .setOfferToken(offerTokenNewPlan)
                    .build()
            )
        )
        .setSubscriptionUpdateParams(
            BillingFlowParams.SubscriptionUpdateParams.newBuilder()
                .setOldPurchaseToken(oldToken)
                .setReplaceProrationMode(BillingFlowParams.ProrationMode.IMMEDIATE_AND_CHARGE_FULL_PRICE)
                .build()
            )
            .build()
    
    BillingClient.launchBillingFlow(activity, billingFlowParams)
    

    Java

    BillingFlowParams billingFlowParams =
            BillingFlowParams.newBuilder()
                .setProductDetailsParamsList(
                    ImmutableList.of(
                        ProductDetailsParams.newBuilder()
                            // Fetched via queryProductDetailsAsync
                            .setProductDetails(productDetailsNewPlan)
                            // offerIdToken can be found in
                            // ProductDetails=>SubscriptionOfferDetails.
                            .setOfferToken(offerTokenNewPlan)
                            .build()
                    )
                )
                .setSubscriptionUpdateParams(
                    SubscriptionUpdateParams.newBuilder()
                        // purchaseToken can be found in
                        // Purchase#getPurchaseToken
                        .setOldPurchaseToken("old_purchase_token")
                        .setReplaceProrationMode(ProrationMode.IMMEDIATE_AND_CHARGE_FULL_PRICE)
                        .build()
                )
                .build();
    
    BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);
    

この購入は Google Play の課金システムで行われ、アプリは購入の結果とともに PurchasesUpdatedListener.onPurchaseUpdated 呼び出しを受け取ります。購入が成功すると、onPurchaseUpdated メソッドも新しい購入情報を受け取り、バックエンドは SUBSCRIPTION_PURCHASED リアルタイム デベロッパー通知を受け取ります。新しい購入のステータスを取得する際、linkedPurchaseToken 属性は以前の定期購入にリンクされているため、推奨されている方法で破棄できます。

定期購入の解約と再開

ユーザーはいつでも定期購入を解約できる必要があります。ユーザーが定期購入を解約したとき、利用資格の停止は購入済みの期間が終了するまで延期されることがあります。たとえば、ユーザーが月の中旬で月次の定期購入を解約した場合、そのアクセス権が削除されるまで、残りの約 2 週間は引き続きサービスにアクセスできます。この期間中、定期購入は技術的に有効であるため、ユーザーはサービスを利用できます。

この有効な期間に解約が取り消されることは珍しくありません。このガイドではこれを再開EMと呼びます。以降のセクションでは、代替の課金システムの API 統合で再開のシナリオを処理する方法について説明します。

代替の課金システムで購入した定期購入

解約された定期購入の外部取引 ID がある場合は、定期購入の再開に launchBillingFlow の呼び出しは不要なため、このタイプの有効化には使用しないでください。解約された定期購入がまだ有効な間にユーザーが定期購入を再開した場合、その時点で取引は発生しません。現在のサイクルが終了して次の更新が発生したときに更新を報告することは可能です。これには、ユーザーが再開の一環としてクレジットや特別な更新価格を受け取る場合も含まれます(定期購入を継続するようユーザーに促すプロモーションなど)。

Google Play の課金システムで購入した定期購入

通常、ユーザーは Google Play の課金システムで定期購入を再開できます。もともと Google Play の課金システムで購入した解約済みの定期購入については、定期購入が有効な間、ユーザーは Google Play の再度定期購入機能で解約を取り消すことができます。その場合、バックエンドで SUBSCRIPTION_RESTARTED リアルタイム デベロッパー通知を受け取ります。また、新しい購入トークンは発行されません。元のトークンが定期購入の継続に使用されます。Google Play の課金システムで再開を管理する方法については、定期購入管理ガイドの再開をご覧ください。

また、launchBillingFlow を呼び出すことで、アプリから Google Play の課金システムで再開をトリガーすることもできます。その方法については、定期購入の有効期限前 - アプリ内をご覧ください。もともとの購入のユーザー選択フロー(解約したがまだ有効)をユーザーが進めた場合、システムはその選択を自動的に検出し、その購入を再開するためのユーザー インターフェースを表示します。Google Play で定期購入の再購入を行うよう求められますが、ユーザー選択を再度行う必要はありません。この場合は、ユーザーに新しい購入トークンが発行されます。バックエンドが SUBSCRIPTION_PURCHASED リアルタイム デベロッパー通知を受信し、新しい購入ステータスの linkedPurchaseToken 値が、アップグレードまたはダウングレードの場合と同様に、解約された定期購入の以前の購入トークンに設定されます。

再度定期購入

定期購入が完全に期限切れになった場合、その理由が解約や回復しない支払い不承認(アカウントの一時停止の期限切れ)であっても、ユーザーが利用資格の再開を望む場合には「再度定期購入」を行う必要があります。

再度定期購入は、通常の登録と同様に、それを処理することでアプリを通じて有効にすることもできます。ユーザーが使用する課金システムを選択できるようにする必要があります。その場合は、ユーザー選択型決済のフローを開始するで説明されているように launchBillingFlow を呼び出します。

次のステップ

アプリ内統合が完了すると、バックエンドを統合する準備が整います。