ユーザー選択型決済のアプリ内統合のガイダンス

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

Play Billing Library のセットアップ

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

Google Play に接続する

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

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

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

Kotlin

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

val userChoiceBillingListener =
   UserChoiceBillingListener { userChoiceDetails ->
       // Handle alternative billing choice.
   }

var billingClient = BillingClient.newBuilder(context)
   .setListener(purchasesUpdatedListener)
   .enablePendingPurchases()
   .enableUserChoiceBilling(userChoiceBillingListener)
   .build()

Java

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

private UserChoiceBillingListener userChoiceBillingListener = new UserChoiceBillingListener() {
    @Override
    public void userSelectedAlternativeBilling(
        UserChoiceDetails userChoiceDetails) {
        // Handle new Google Play purchase.
    }
};

private BillingClient billingClient = BillingClient.newBuilder(context)
    .setListener(purchasesUpdatedListener)
    .enablePendingPurchases()
    .enableUserChoiceBilling(userChoiceBillingListener)
    .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 のセットアップ中に enableUserChoiceBilling が呼び出される

ユーザー選択の UX が表示される

Google Play 請求サービスの標準 UX が表示される

BillingClient のセットアップ中に enableUserChoiceBilling が呼び出されない

Google Play 請求サービスの標準 UX が表示される

Google Play 請求サービスの標準 UX が表示される

ユーザー選択を処理する

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

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

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

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

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

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

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

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

Kotlin

private val userChoiceBillingListener =
    UserChoiceBillingListener { userChoiceDetails ->
        // Get the products being purchased by the user.
        val products = userChoiceDetails.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(
            userChoiceDetails.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 userChoiceBillingListener userChoiceBillingListener = new UserChoiceBillingListener() {
    @Override
    public void userSelectedAlternativeBilling(
           UserChoiceDetails userChoiceDetails) {
       // Get the products being purchased by the user.
       List<Product> products =
              userChoiceDetails.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(
              userChoiceDetails.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() を使用して新しい購入を開始します。

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

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

これを行うには、ユーザーがアップグレードまたはダウングレードをリクエストしたときに 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 UserChoiceBillingListener 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 UserChoiceBillingListener is triggered.

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

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

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

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

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

String offerTokenNewPlan = productDetailsNewPlan
                     .getSubscriptionOfferDetails(selectedOfferIndex)
                     .getOfferToken();

  1. 既存の定期購入の購入トークンなど、新しい購入を処理するために正しい情報を Google Play の課金システムに送信します。

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)

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() を呼び出します。

代替の課金システムをテストする

代替の課金システムの統合をテストするには、ライセンス テスターを使用する必要があります。ライセンス テスター アカウントによって開始された取引については、請求は発生しません。ライセンス テスターの設定について詳しくは、アプリ ライセンスを使用してアプリ内課金をテストするをご覧ください。

次のステップ

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