外部決済のアプリ内統合のガイダンス

このドキュメントでは、Google Play Billing Library API を統合して、対象アプリで外部決済を提供する方法について説明します。このプログラムの詳細については、プログラムの要件をご覧ください。

Play Billing Library のセットアップ

Android アプリに Play Billing Library の依存関係を追加します。外部決済システムの API を使用するには、バージョン 8.3 以降を使用する必要があります。以前のバージョンから移行する必要がある場合は、移行ガイドの手順に沿ってアップグレードしてから、インテグレーションを開始してください。

課金クライアントを初期化する

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

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

Kotlin

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

val developerProvidedBillingListener =
    DeveloperProvidedBillingListener { details ->
        // Handle user selection for developer provided billing option.
    }

val billingClient = BillingClient.newBuilder(context)
    .setListener(purchasesUpdatedListener)
    .enablePendingPurchases()
    .enableBillingProgram(
        EnableBillingProgramParams.newBuilder()
            .setBillingProgram(BillingProgram.EXTERNAL_PAYMENTS)
            .setDeveloperProvidedBillingListener(developerProvidedBillingListener)
            .build())
    .build()

Java

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

private DeveloperProvidedBillingListener developerProvidedBillingListener =
    new DeveloperProvidedBillingListener() {
        @Override
        public void onUserSelectedDeveloperBilling(
            DeveloperProvidedBillingDetails details) {
            // Handle user selection for developer provided billing option.
        }
    };

private BillingClient billingClient = BillingClient.newBuilder(context)
    .setListener(purchasesUpdatedListener)
    .enablePendingPurchases()
    .enableBillingProgram(
        EnableBillingProgramParams.newBuilder()
            .setBillingProgram(BillingProgram.EXTERNAL_PAYMENTS)
            .setDeveloperProvidedBillingListener(developerProvidedBillingListener)
            .build())
    .build();

Google Play に接続する

BillingClient を初期化したら、Google Play に接続するの説明に沿って Google Play に接続します。

お客様が対象であるか確認する

Google Play に接続したら、isBillingProgramAvailableAsync() メソッドを呼び出して、ユーザーが外部決済プログラムの対象かどうかを確認できます。このメソッドは、ユーザーが対象となる場合は BillingResponseCode.OK を返します。次のサンプルは、利用資格を確認する方法を示しています。

Kotlin

billingClient.isBillingProgramAvailableAsync(
  BillingProgram.EXTERNAL_PAYMENTS,
  object : BillingProgramAvailabilityListener {
    override fun onBillingProgramAvailabilityResponse(
      billingProgram: Int, billingResult: BillingResult) {
        if (billingResult.responseCode != BillingResponseCode.OK) {
            // Handle failures such as retrying due to network errors,
            // handling external payments unavailable, etc.
            return
        }

        // External payments are available. Can proceed with generating an
        // external transaction token.
})

Java

billingClient.isBillingProgramAvailableAsync(
  BillingProgram.EXTERNAL_PAYMENTS,
  new BillingProgramAvailabilityListener() {
    @Override
    public void onBillingProgramAvailabilityResponse(
      int billingProgram, BillingResult billingResult) {
        if (billingResult.getResponseCode() != BillingResponseCode.OK) {
            // Handle failures such as retrying due to network errors,
            // handling external payments unavailable, etc.
            return;
        }

        // External payments are available. Can proceed with generating an external transaction token.
      }

    });

他のレスポンス コードに対応する方法については、レスポンス処理をご覧ください。Kotlin 拡張機能を使用している場合は、Kotlin コルーチンを使用できるため、リスナーを別に定義する必要はありません。

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

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

外部取引トークンを準備する

外部取引を Google Play に報告するには、Play Billing Library で生成された外部取引トークンが必要です。ユーザーが外部決済 API を介して外部のウェブサイトやアプリにアクセスするたびに、新しい外部取引トークンを生成する必要があります。これを行うには、createBillingProgramReportingDetailsAsync API を呼び出します。トークンは、launchBillingFlow が呼び出される直前に生成する必要があります。

Kotlin

val params =
    BillingProgramReportingDetailsParams.newBuilder()
        .setBillingProgram(BillingProgram.EXTERNAL_PAYMENTS)
        .build()

billingClient.createBillingProgramReportingDetailsAsync(
  params,
  object : BillingProgramReportingDetailsListener {
    override fun onCreateBillingProgramReportingDetailsResponse(
      billingResult: BillingResult,
      billingProgramReportingDetails: BillingProgramReportingDetails?) {
        if (billingResult.responseCode != BillingResponseCode.OK) {
            // Handle failures such as retrying due to network errors.
            return
        }
        val externalTransactionToken =
            billingProgramReportingDetails?.externalTransactionToken
        // Persist the external transaction token locally. Pass it to
        // the external website using DeveloperBillingOptionParams when
        // launchBillingFlow is called.
    }
})

Java

BillingProgramReportingDetailsParams params =
    BillingProgramReportingDetailsParams.newBuilder()
        .setBillingProgram(BillingProgram.EXTERNAL_PAYMENTS)
        .build();

billingClient.createBillingProgramReportingDetailsAsync(
  params,
  new BillingProgramReportingDetailsListener() {
    @Override
    public void onCreateBillingProgramReportingDetailsResponse(
      BillingResult billingResult,
      @Nullable BillingProgramReportingDetails
        billingProgramReportingDetails) {
        if (billingResult.getResponseCode() != BillingResponseCode.OK) {
            // Handle failures such as retrying due to network errors.
            return;
        }

        String transactionToken =
          billingProgramReportingDetails.getExternalTransactionToken();

        // Persist the external transaction token locally. Pass it to
        // the external website using DeveloperBillingOptionParams when
        // launchBillingFlow is called.
      }
});

Kotlin 拡張機能を使用している場合は、Kotlin コルーチンを使用できるため、リスナーを別に定義する必要はありません。

外部決済フローの開始

launchBillingFlow() を呼び出して外部決済フローを開始します。これは、Google Play 課金システムの統合を使用した購入フローの開始と似ていますが、アプリがこの購入で外部決済フローを有効にしたいことを示す追加のパラメータ DeveloperBillingOptionParams が指定されています。

DeveloperBillingOptionParams には、次のものが含まれている必要があります。

  • billingProgramEXTERNAL_PAYMENTS 課金プログラムに設定されました
  • linkURI をリンク先に設定
  • Google Play がリンクを起動する場合は launchModeLAUNCH_IN_EXTERNAL_BROWSER_OR_APP に設定し、アプリがリンクを起動する場合は CALLER_WILL_LAUNCH_LINK に設定します。

アプリが DeveloperBillingOptionParams を指定して launchBillingFlow() を呼び出すと、Google Play 請求サービスが次のチェックを実行します。

  • システムは、ユーザーの Google Play の国が、外部決済に対応している国(サポート対象国)かどうかをチェックします。ユーザーの Google Play の国がサポート対象国の場合、Google Play は、BillingClient の設定と DeveloperBillingOptionParams が提供されているかどうかに基づいて、外部支払いが有効になっているかどうかをチェックします。
    • 外部決済が有効になっている場合は、購入フローでユーザー選択型の UX が表示されます。
    • 外部決済が有効になっていない場合、購入フローには、ユーザー選択なしで標準の Google Play 課金システムの UX が表示されます。
  • ユーザーの Google Play の国がサポート対象国でない場合、購入フローには、Google Play 請求サービスの標準 UX(ユーザー選択型ではない)が表示されます。

ユーザーの Play の国がサポート対象国

ユーザーの Play の国がサポート対象国以外

外部決済が有効(BillingClient のセットアップlaunchBillingFlow

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

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

外部支払いが有効になっていない(BillingClient のセットアップ中に有効になっていないか、launchBillingFlow に DeveloperBillingOptionParams が提供されていない)

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

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

次のスニペットは、DeveloperBillingOptionParams の作成方法を示しています。

Kotlin

val developerBillingOptionParams =
    DeveloperBillingOptionParams.newBuilder()
        .setBillingProgram(BillingProgram.EXTERNAL_PAYMENTS)
        .setLinkUri("https://www.example.com/external/purchase")
        .setLaunchMode(
            DeveloperBillingOptionParams.LaunchMode.LAUNCH_IN_EXTERNAL_BROWSER_OR_APP)
        .build()

Java

DeveloperBillingOptionParams developerBillingOptionParams =
    DeveloperBillingOptionParams.newBuilder()
        .setBillingProgram(BillingProgram.EXTERNAL_PAYMENTS)
        .setLinkUri("https://www.example.com/external/purchase")
        .setLaunchMode(
            DeveloperBillingOptionParams.LaunchMode.LAUNCH_IN_EXTERNAL_BROWSER_OR_APP)
        .build();

ユーザー選択を処理する

残りの購入フローの処理方法は、ユーザーが Google Play の課金システムを選択するか、ウェブサイトでの支払いを選択するかによって異なります。

ユーザーがウェブサイトまたは決済アプリで支払うことを選択した場合

ユーザーがウェブサイトで支払うことを選択すると、Google Play は DeveloperProvidedBillingListener を呼び出し、ユーザーがウェブサイトまたは支払いアプリで支払うことを選択したことをアプリに通知します。具体的には、onUserSelectedDeveloperBilling() メソッドが呼び出されます。

アプリで launchModeLAUNCH_IN_EXTERNAL_BROWSER_OR_APP に設定すると、Google Play がリンクを起動します。launchModeCALLER_WILL_LAUNCH_LINK に設定されている場合、リンクの起動はアプリの責任となります。ユーザーをお支払いアプリにリンクする際は、ユーザーのデバイスにお支払いアプリがすでにインストールされていることを確認する必要があります。

このトークンは、バックエンド統合ガイドの説明のとおり、この選択から発生する取引を報告するために使用します。

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

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

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

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

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

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

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

アップグレードやダウングレードのフローを含む定期購入プランの変更は、定期購入を Google Play の課金システムとデベロッパーのウェブサイトのどちらで処理したかによって、異なる処理を行う必要があります。

既存の定期購入に依存し、同じお支払い方法を使用し、定期請求が一致するアドオンは、アップグレードとして処理されます。その他のアドオンについては、ユーザーが使用する課金システムを選択できるようにする必要があります。外部支払いフローの開始で説明されているように、launchBillingFlow() を使用して新しい購入フローを開始します。

デベロッパーのウェブサイトまたは決済アプリで購入した定期購入

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

これを行うには、ユーザーがアップグレードまたはダウングレードをリクエストしたときに launchBillingFlow() を呼び出します。SubscriptionUpdateParams オブジェクトで他のパラメータを指定する代わりに、setOriginalExternalTransactionId() を使用して、元の購入の外部取引 ID を指定します。

この呼び出しでは DeveloperBillingOptionParams も指定する必要があります。元の購入のユーザー選択がアップグレードとダウングレードで変わっていなければ、ユーザー選択画面は表示されません。こちらの説明に沿って、この取引の新しい外部取引トークンを生成する必要があります。

デベロッパーのウェブサイトまたは決済アプリを使用してアップグレードまたはダウングレードが完了したら、新しい定期購入に関する上記の呼び出しで取得した外部取引トークンを使用して新しい取引を報告する必要があります。

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

同様に、ユーザー選択後に Google Play の課金システムで現在の定期購入を購入したユーザーには、Google Play 請求サービスの標準フローが表示されます。launchBillingFlow の呼び出しで DeveloperBillingOptionParams を設定してはなりません。

定期購入の解約と再開

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

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

デベロッパーのウェブサイトで購入した定期購入

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

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

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

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

再度定期購入

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

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

レスポンス処理

エラーが発生した場合、メソッド isBillingProgramAvailableAsync()createBillingProgramReportingDetailsAsync()launchBillingFlow()BillingResponseCode.OK 以外の BillingResponseCode を提供する可能性があります。これらのレスポンス コードは次のように処理することを検討してください。

  • BillingResponseCode.ERROR: これは内部エラーです。取引や外部ウェブサイトのオープンを続行しないでください。API を再度呼び出して再試行します。
  • BillingResponseCode.FEATURE_NOT_SUPPORTED: 外部決済 API が、現在のデバイスの Google Play ストアでサポートされていません。取引や外部ウェブサイトのオープンを続行しないでください。
  • BillingResponseCode.DEVELOPER_ERROR: リクエストでエラーが発生しています。先に進む前に、デバッグ メッセージを使用してエラーを特定および修正してください。
  • BillingResponseCode.USER_CANCELED: 外部のウェブサイトやアプリを開く処理を続行しないでください。次回ユーザーをアプリ外に誘導しようとしたときに情報ダイアログを表示するため、再度 launchBillingFlow() を呼び出してください。
  • BillingResponseCode.BILLING_UNAVAILABLE: 取引が外部決済の対象ではないため、このプログラムではデベロッパーの課金を利用できません。このエラーは、ユーザーがこのプログラムの対象国に居住していないか、アカウントがプログラムに正常に登録されていない場合に発生します。後者の場合は、Google Play Console で登録ステータスを確認してください。
  • BillingResponseCode.NETWORK_ERRORBillingResponseCode.SERVICE_DISCONNECTEDBillingResponseCode.SERVICE_UNAVAILABLE: これらは一時的なエラーであり、適切な再試行ポリシーで処理する必要があります。SERVICE_DISCONNECTED の場合は、Google Play との接続を再確立してから再試行してください。

外部決済リンクをテストする

ライセンス テスターは、外部決済の統合をテストするために使用する必要があります。ライセンス テスター アカウントによって開始された取引については、請求されません。ライセンス テスターの構成について詳しくは、アプリ ライセンスを使用したアプリ内課金のテストをご覧ください。

次のステップ

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