このトピックでは、更新や有効期限など、定期購入のライフサイクル イベントを処理する方法について説明します。また、プロモーションの提供やユーザーによる定期購入の管理など、その他の定期購入機能についても説明します。
アプリの定期購入アイテムを構成していない場合は、アイテムを作成して構成するをご覧ください。
定期購入の概要
定期購入は、指定された期間にユーザーが利用できる特典のセットを表します。たとえば、定期購入により、ユーザーは音楽ストリーミング サービスの利用資格を獲得できます。
同じアプリ内に複数の定期購入を設定して、異なる特典セットや、単一の特典セットの異なる階層(シルバー階層、ゴールド階層など)を提供できます。
基本プランと特典を使用して、同じ定期購入アイテムについて複数の構成を作成できます。たとえば、アプリを定期購入したことがないユーザーを対象とするお試し特典を作成できます。同様に、すでに定期購入しているユーザーを対象とするアップグレード特典を作成できます。
定期購入商品、基本プラン、特典の詳細については、Google Play Console ヘルプセンターのドキュメントをご覧ください。
プリペイド プランの統合
プリペイド プランは、有効期限が切れても自動的に更新されません。ユーザーが定期購入の利用資格を中断なしで延長するには、同じ定期購入にプリペイド プランをチャージする必要があります。
チャージするには、元の購入の場合と同様に請求フローを開始します。購入がチャージであることを示す必要はありません。
プリペイド プランのチャージでは常に CHARGE_FULL_PRICE
交換モードが使用されるため、このモードを明示的に設定する必要はありません。ユーザーは直ちに請求対象期間の全額を請求され、チャージで指定した期間について利用資格が延長されます。
チャージされると、最新のチャージ購入を反映するために、Purchase
結果オブジェクトの以下のフィールドが更新されます。
- 注文 ID
- 購入時間
- 署名
- 購入トークン
- 承認済み
Purchase
の以下のフィールドには、常に元の購入と同じデータが格納されます。
- パッケージ名
- 購入ステータス
- アイテム
- 自動更新
プリペイド購入の承認
自動更新される定期購入と同様に、デベロッパーはプリペイド プランも購入後に承認する必要があります。初回購入とチャージの両方で承認が必要です。詳細については、購入を処理するをご覧ください。
プリペイド プランの期間が短い可能性があるため、できるだけ早く購入を承認することが重要です。
期間が 1 週間以上のプリペイド プランは、3 日以内に承認する必要があります。
期間が 1 週間未満のプリペイド プランは、プラン期間の半分以内に承認する必要があります。たとえば、3 日間のプリペイド プランの承認期限は 1.5 日間です。
分割払いの定期購入の統合
分割払い定期購入は、ユーザーが定期購入料金全額を事前に支払うのではなく、一定期間にわたって複数回の分割払いを行う定期購入の一種です。
分割払いの定期購入に関するその他の考慮事項:
- 利用可能な国: 分割払い定期購入機能は、ブラジル、フランス、イタリア、スペインでのみご利用いただけます(最新が利用可能かどうかは Google Play Console でご確認ください)。
- 価格の設定: Console で分割払い定期購入の価格を設定する場合、価格は毎月の支払額を表します。この値と、設定されているコミットメント期間を組み合わせることで、購入画面で定期購入の合計額が生成されます。
- コミットメント期間: 最初のサブスクリプション コミットメントの合計期間。この期間中は月額料金が必要になります。たとえば、基本プランに 15 か月のコミットメント期間がある場合、ユーザーはこの期間に 15 か月払いします。
- 更新: 分割払いサブスクリプションのコンテキストでは、「更新」とは、コミットメント期間(最初のコミットメント期間または後続のコミットメント期間)の終了を意味します。最初の登録後、最初のコミットメント期間が終了した時点で最初の更新が行われます。その後の更新は、後続のコミットメント期間が終了した後に行われます。分割払い定期購入の更新タイプは、「毎月自動更新」または「同じ期間で自動更新」のいずれかです。「毎月自動更新」の場合、後続のコミットメントはなく、プランは月単位の定期購入(月単位の定期購入の課金ごとに更新)のように動作します。
- 請求対象期間: 分割払い定期購入では、基本プランで指定されている定期的な支払い間隔を指します。
- プランの変更と価格変更の動作: 価格の変更と解約の場合、コミットメントは確定します。つまり、ユーザーがキャンセルや価格の変更を希望する場合、コミットメント期間の終了時に変更が有効になります。プラン変更の場合、コミットメントは確定ではありません。つまり、プラン変更はコミットメント期間の終了まで待つ必要がなく、すぐに、または設定された交換モードに基づいて次の支払い日に有効になります。
- 同じ定期購入プランの変更: 同じ定期購入プロダクトの分割払いの基本プランから分割払い以外の基本プランへの変更は許可されません。
リアルタイム デベロッパー通知(RTDN): 支払いがコミットメント期間内であれば、ユーザーがキャンセルするとすぐに
SUBSCRIPTION_CANCELLATION_SCHEDULED
RTDN が送信されます。キャンセルは保留中で、コミットメント期間の終了時に有効になります。ユーザーが復元しなかった場合は、コミットメント期間の終了時にSUBSCRIPTION_CANCELED
とSUBSCRIPTION_EXPIRED
の RTDN が送信されます。支払い / 収益の実現: デベロッパーへの支払いは、他のすべての定期購入と同じ条件に沿って、ユーザーが月額料金を支払うと行われます。ユーザーが分割払い定期購入を登録しても、デベロッパーへの前払いは行われません。
回収できなかった支払いの回収: ユーザーが定期購入の支払いに失敗した場合、Google とデベロッパーは、かかる支払いの未履行または未払い料金をユーザーから回収しようとしません。ただし、Google は、該当する猶予期間またはアカウントの一時停止期間中に、通常の支払い再試行方法に従って支払いを定期的に再試行できるものとします。Google は、未払いの分割払いの残りの金額について、デベロッパーに対して責任を負いません。
Play Billing Library の提供状況:
installmentDetails
フィールドは PBL 7 以降でのみ使用できます。PBL 5 以降では、queryProductDetails()
を使用して分割払いの定期購入が返されますが、定期購入の確約された支払い回数など、分割払いの詳細情報は含まれません。
ディープリンクを使用してユーザーが定期購入を管理できるようにする
アプリのデザインに合わせて、アプリの設定画面にユーザーが定期購入を管理するためのリンクを組み込みます。
有効期限内の定期購入について、アプリから Google Play 定期購入センターへのディープリンクを追加できます。これは、定期購入リソースの subscriptionState
フィールドで判断できます。これに基づいて、いくつかの方法で Google Play ストアの定期購入センターへのディープリンクを設定できます。
定期購入センターへのリンク
次の URL を使用して、図 1 と図 2 に示すように、すべての定期購入を表示するページにユーザーを誘導します。
https://play.google.com/store/account/subscriptions
![Google Play ストアの定期購入画面に表示される、Google Play で請求されたユーザーのすべての定期購入のステータス。](https://developer.android.com/static/images/google/play/billing/sub_center_general.png?authuser=7&hl=ja)
![さらに詳しい情報を表示するには、定期購入をタップします。](https://developer.android.com/static/images/google/play/billing/sub_management_mock_general.png?authuser=7&hl=ja)
このディープリンクは、ユーザーが Google Play ストアの定期購入センターから解約した定期購入を再開する際に役立ちます。
特定の定期購入の管理ページへのリンク(推奨)
有効期限内の定期購入の管理ページに直接リンクするには、購入した定期購入に関連付けられているパッケージ名と productId
を指定します。プログラマティックに既存の定期購入の productId
を確認するには、個々のユーザーに関連付けられている定期購入のリストをアプリのバックエンドに照会するか、BillingClient.queryPurchasesAsync()
を呼び出します。各定期購入には、定期購入のステータス情報の一部として、対応する productId
が含まれます。定期購入に関連付けられた各 SubscriptionPurchaseLineItem
オブジェクトには、ユーザーがその項目で購入した定期購入に関連付けられた productId
が含まれます。
次の URL を使用してユーザーを特定の定期購入管理画面に誘導します。「your-sub-product-id」と「your-app-package」はそれぞれ productId
とアプリのパッケージ名に置き換えてください。
https://play.google.com/store/account/subscriptions?sku=your-sub-product-id&package=your-app-package
これにより、ユーザーはお支払い方法を管理したり、解約、再度定期購入、一時停止などの機能にアクセスしたりできるようになります。
ユーザーが定期購入をアップグレード、ダウングレード、変更できるようにする
既存の定期購入者に、ニーズに合わせて定期購入プランを変更するためのさまざまなオプションを提供できます。
- 「基本」定期購入と「プレミアム」定期購入など、複数の定期購入の階層を販売する場合は、ユーザーが別の定期購入の基本プランまたは特典を購入することで、階層を切り替えられるようにできます。
- 月間プランから年間プランへの切り替えなど、現在の請求対象期間を変えられるようにできます。
- また、ユーザーが自動更新プランとプリペイド プランを切り替えられるようにもできます。
要件を満たすユーザーに定期購入特典として割引を提供することで、こうした変更を促進できます。たとえば、月間プランから年間プランに切り替えると初年度に 50% 割引を提供する特典を作成し、月額プランを定期購入中でこの特典を購入していないユーザー限定の特典にできます。特典の利用条件について詳しくは、ヘルプセンターをご覧ください。
図 3 は、3 つの異なるプランを表示したサンプルアプリを示しています。
![3 つの定期購入階層があるアプリ。](https://developer.android.com/static/images/google/play/billing/plan_change_inapp.png?authuser=7&hl=ja)
アプリに、図 3 のような画面を表示して、定期購入を変更するオプションをユーザーに提供できます。いずれの場合も、現在の定期購入プランの内容と、変更オプションをユーザーに明確に示す必要があります。
ユーザーが定期購入をアップグレード、ダウングレード、変更する場合は、交換モードを指定します。交換モードでは、現在の支払済み請求対象期間の比例配分額がどのように適用されるか、また利用資格が変更される時期が決定されます。
交換モード
次の表に、利用可能な交換モードと使用例、有料と見なされる支払い回数を示します。
交換モード |
説明 |
使用例 |
確約済みのお支払いが支払い済みとして記録される(分割払いの定期購入の置き換え) |
|
定期購入は直ちにアップグレードまたはダウングレードされます。残りの期間は価格の差に応じて調整され、次回の請求日との差分が新しい定期購入に充当されます。これがデフォルト設定です。 |
すぐに追加料金なしで、より高額なプランにアップグレードできます。 |
0 |
|
定期購入は直ちにアップグレードされますが、請求期間は変わりません。ユーザーには残りの期間の差額が請求されます。 注: このオプションは、時間単位の料金が引き上げられる定期購入のアップグレードでのみ利用できます。 |
請求日を変更せずに、より高額なプランにアップグレードできます。 |
1 |
|
定期購入は直ちにアップグレードまたはダウングレードされ、新しい利用資格の全額が直ちに請求されます。以前の定期購入の残額は、同じ利用資格に引き継がれるか、別の利用資格への切り替え時に期間内で比例配分されます。 注: 新しい定期購入に無料試用またはお試し特典が含まれている場合、アップグレードまたはダウングレードの時点で、ユーザーには $0 またはお試し特典の価格(いずれか該当する方)が請求されます。 |
請求対象期間が短いものから長いものにアップグレードします。 |
1(注: 新しいサブスクリプションに無料試用が含まれている場合は 0) |
|
定期購入は直ちにアップグレードまたはダウングレードされ、定期購入の更新時に新しい価格が請求されます。請求期間は変わりません。 |
残りの無料期間はそのままで、上位のサブスクリプションにアップグレードできます。 |
0 |
|
定期購入は更新時にのみアップグレードまたはダウングレードされますが、新しい購入は直ちに発行され、新しい利用資格の開始日は将来に設定されるため、ユーザーが必要に応じて追加の変更を行えるようにできます。たとえば、元のプランに戻したり、新しい延期されたプラン変更を開始したりできます。注: 分割払いサブスクリプションの場合、プランの変更は次の支払い日の開始時に行われます。 |
より低額な階層にダウングレードします。 |
1 |
アップグレード特典、またはダウングレード特典のさまざまなアップセルおよび再獲得の適用について詳しくは、特典とプロモーションのガイドをご覧ください。
購入の交換モードを設定する
設定とビジネス ロジックに基づき、定期購入移行のタイプに応じたさまざまな交換モードを使用できます。このセクションでは、定期購入の変更に対して交換モードを設定する方法と、適用される制限事項について説明します。
再度定期購入、または同じ定期購入内でのプランの切り替えを行う
Google Play Console でデフォルトの交換モードを指定できます。この設定では、現在の定期購入ユーザーが同じ定期購入の別の基本プランや特典を購入した場合や、解約後に再度定期購入した場合の請求のタイミングを選択します。利用可能なオプションは、[すぐに請求](CHARGE_FULL_PRICE
と同等)と [次回の請求日に請求](WITHOUT_PRORATION
と同等)です。同じ定期購入内で基本プランを切り替える場合に関連する交換モードはこれらのみです。
たとえば、ユーザーが解約した後、定期購入が終了する前のタイミングで、同じプランの再獲得特典を実装する場合、SubscriptionUpdateParams
に値を指定せずに通常の購入として新しい購入を処理できます。システムは、定期購入で構成したデフォルトの交換モードを使用し、以前の購入から新しい購入へのプランの移行を自動的に処理します。
定期購入間でプランを切り替える、またはデフォルトの交換モードをオーバーライドする
ユーザーが定期購入のアイテムを変更する場合(別の定期購入を購入する場合)、またはなんらかの理由でデフォルトの交換モードをオーバーライドする場合は、実行時に購入フロー パラメータの一部として比例配分率を指定します。
実行時購入フロー構成の一部として SubscriptionUpdateParams
を正しく指定するには、次の制限事項に注意してください。
- 定期購入をアップグレードまたはダウングレードする場合、あるいはプリペイド プラン、自動更新プラン、分割払いプランからプリペイド プランへ切り替える場合、許可される交換モードは
CHARGE_FULL_PRICE
のみです。他の交換モードを指定すると、購入は失敗し、ユーザーにエラーが表示されます。 - 同じ定期購入内でプランをプリペイド プランまたは自動更新プランから自動更新プランへと切り替える場合、有効な比例配分モードは
CHARGE_FULL_PRICE
とWITHOUT_PRORATION
です。他の比例配分モードを指定すると、購入は失敗し、ユーザーに対してエラーが表示されます。 - 同じ定期購入プロダクト内でのプランを分割払いの基本プランから非分割払いの基本プランに切り替えることはできません。
交換の例と動作
各比例配分モードの仕組みを理解するために、次の事例について考えてみましょう。
あるユーザーが「Country Gardener」というアプリのオンライン コンテンツを定期購入しており、そのコンテンツの Tier 1 バージョン(テキストのみ)を月次定期購入しています。この定期購入の料金は月額 2 ドルで、毎月 1 日に更新されます。
4 月 15 日に、Tier 2 定期購入の年間バージョンにアップグレードすることにしました。これには動画のアップデートが含まれ、料金は年間 36 ドルです。
デベロッパーは定期購入のアップグレードに、比例配分モードを選択しています。各比例配分モードがユーザーの定期購入にどのように影響するのかを、以下のリストに示します。
WITH_TIME_PRORATION
ユーザーの Tier 1 の定期購入は直ちに終了します。ユーザーは 1 か月分(4 月 1~30 日)をすでに支払っていますが、定期購入期間が半分経過した時点でアップグレードしたため、月次定期購入分の残り半分(1 ドル)は新しい定期購入に適用されます。ただし、この新しい定期購入の年間料金が 36 ドルであることから、1 ドルのクレジット残高で支払えるのは 10 日分(4 月 16~25 日)のみとなります。したがって 4 月 26 日に新しい定期購入分の 36 ドルが請求され、以後毎年 4 月 26 日に 36 ドルが請求されます。
購入が完了した時点でアプリの PurchasesUpdatedListener
を呼び出すことで、queryPurchasesAsync()
呼び出しの一部として新しい購入を取得できます。バックエンドはすぐに SUBSCRIPTION_PURCHASED
リアルタイム デベロッパー通知を受け取ります。
CHARGE_PRORATED_PRICE
Tier 2 の定期購入の単位時間あたり価格(36 ドル/年 = 3 ドル/月)が、Tier 1 の定期購入の単位時間あたり価格(2 ドル/月)よりも高いため、このモードが使用できます。ユーザーの Tier 1 の定期購入は直ちに終了します。ユーザーは 1 か月分をすでに支払っていますが、半分しか使用していないため、月次定期購入分の残り半分(1 ドル)は新しい定期購入に適用されます。ただし、新しい定期購入の料金が 36 ドル/年であり、残りの 15 日分の料金は 1.5 ドルであるため、新しい定期購入については差分の 0.5 ドルが請求されます。5 月 1 日には新しい定期購入の 36 ドルが請求され、以後毎年 5 月 1 日に 36 ドルが請求されます。
購入が完了した時点でアプリの PurchasesUpdatedListener
を呼び出すことで、queryPurchasesAsync()
呼び出しの一部として新しい購入を取得できます。バックエンドはすぐに SUBSCRIPTION_PURCHASED
リアルタイム デベロッパー通知を受け取ります。
WITHOUT_PRORATION
ユーザーの Tier 1 の定期購入は直ちに追加料金なしで Tier 2 にアップグレードされます。5 月 1 日には新しい定期購入について 36 ドルが請求され、以後毎年 5 月 1 日に 36 ドルが請求されます。
購入が完了した時点でアプリの PurchasesUpdatedListener
を呼び出すことで、queryPurchasesAsync()
呼び出しの一部として新しい購入を取得できます。バックエンドはすぐに SUBSCRIPTION_PURCHASED
リアルタイム デベロッパー通知を受け取ります。
DEFERRED
ユーザーの Tier 1 の定期購入は 4 月 30 日に期限が切れるまで継続します。5 月 1 日に Tier 2 の定期購入が有効になり、新しい定期購入について 36 ドルが請求されます。
購入が完了した時点でアプリの PurchasesUpdatedListener
を呼び出すことで、queryPurchasesAsync()
呼び出しの一部として新しい購入を取得できます。バックエンドはすぐに SUBSCRIPTION_PURCHASED
リアルタイム デベロッパー通知を受け取ります。その時点で他の新しい購入と同じ方法で購入を処理する必要があります。特に新しい購入の承認が必要です。なお、新しい定期購入の startTime
は、古い定期購入の期限が切れて交換が有効になった時点で入力されます。その時点で、新しい定期購入プランの SUBSCRIPTION_RENEWED
RTDN が送信されます。ReplacementMode.DEFERRED
の動作について詳しくは、交換延期を処理するをご覧ください。
CHARGE_FULL_PRICE
ユーザーの Tier 1 の定期購入は直ちに終了します。その日に Tier 2 の定期購入が開始され、36 ドルが請求されます。ユーザーは 1 か月分をすでに支払っていますが、半分しか使用していないため、月次定期購入分の残り半分(1 ドル)は新しい定期購入に適用されます。新しい定期購入の料金は年間 36 ドルであるため、1 年の 1/36(概算で 10 日)が定期購入期間に追加されます。したがって、次回の請求はその日から 1 年と 10 日後で、36 ドルになります。それ以降は毎年 36 ドルが請求されます。
比例配分モードを選択する際は、交換の推奨事項をご確認ください。
アプリ内で定期購入の変更をトリガーする
アプリでは、購入フローの開始と同じ手順でアップグレードまたはダウングレードを提供できます。ただし、アップグレードまたはダウングレードする場合は、次の例に示すように、現在の定期購入、将来の(アップグレードまたはダウングレードした)定期購入、使用する交換モードの詳細を指定する必要があります。
Kotlin
val offerToken = productDetails .getSubscriptionOfferDetails(selectedOfferIndex) .getOfferToken() val billingParams = BillingFlowParams.newBuilder().setProductDetailsParamsList( listOf( BillingFlowParams.ProductDetailsParams.newBuilder() .setProductDetails(productDetails) .setOfferToken(offerToken) .build() ) ).setSubscriptionUpdateParams( BillingFlowParams.SubscriptionUpdateParams.newBuilder() .setOldPurchaseToken("old_purchase_token") .setSubscriptionReplacementMode( BillingFlowParams.ReplacementMode.CHARGE_FULL_PRICE ) .build() ).build() billingClient.launchBillingFlow( activity, billingParams ) // ...
Java
String offerToken = productDetails .getSubscriptionOfferDetails(selectedOfferIndex) .getOfferToken(); BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder() .setProductDetailsParamsList( ImmuableList.of( ProductDetailsParams.newBuilder() // fetched via queryProductDetailsAsync .setProductDetails(productDetails) // offerToken can be found in // ProductDetails=>SubscriptionOfferDetails .setOfferToken(offerToken) .build())) .setSubscriptionUpdateParams( SubscriptionUpdateParams.newBuilder() // purchaseToken can be found in Purchase#getPurchaseToken .setOldPurchaseToken("old_purchase_token") .setSubscriptionReplacementMode(ReplacementMode.CHARGE_FULL_PRICE) .build()) .build(); BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams); // ...
交換に関する推奨事項
次の表に、さまざまな比例配分のシナリオと、各シナリオでの推奨事項を示します。
シナリオ | 推奨される交換モード | 結果 |
---|---|---|
より高額な階層へのアップグレード | CHARGE_PRORATED_PRICE |
ユーザーは、同じ請求対象期間を維持しながら、直ちにアクセスできるようになります。 |
より低額な階層へのダウングレード | DEFERRED |
ユーザーはすでにより高額な階層で支払い済みであるため、次の請求日までアクセスが継続されます。 |
無料試用期間中のアップグレード | WITHOUT_PRORATION |
ユーザーは無料試用の利用権を保持し、試用期間の残りの期間は上位階層にアップグレードされます。 |
無料試用期間中のアップグレード - 無料試用へのアクセスの終了 | CHARGE_PRORATED_PRICE |
ユーザーはすぐに新しい階層にアクセスできますが、無料試用期間は終了します。 |
定期購入の変更購入を処理する
プランの変更は、事実上新しい購入です。請求フローが正常に完了した場合は、新しい購入として処理し、承認する必要があります。新しい購入を適切に処理するだけでなく、交換される購入を終了する必要があります。
アプリ内での動作は、新しい購入の場合と同じです。アプリは PurchasesUpdatedListener
で新しい購入の結果を受け取り、新しい購入は queryPurchasesAsync
で利用できるようになります。
既存の購入が新しい購入に交換されると、Google Play Developer API は、定期購入リソース内で linkedPurchaseToken
を返します。サービスに対するアクセスに以前のトークンが使用されないように、linkedPurchaseToken
内で提供されるトークンは必ず無効にしてください。アップグレードとダウングレードの購入の処理については、アップグレード、ダウングレード、再登録をご覧ください。
新しい購入トークンを受け取ったら、新しい購入トークンを検証する場合と同じ検証プロセスを行います。Google Play Billing Library の BillingClient.acknowledgePurchase()
、または Google Play Developer API の Purchases.subscriptions:acknowledge
を使用して購入を承認します。
交換延期を処理する
交換延期モードでは、ユーザーは新しいプランを開始する前に、以前のプランの残りの利用資格を消化できます。
新しい購入で ReplacementMode.DEFERRED を使用すると、queryPurchasesAsync()
は購入フロー後に新しい購入トークンを返しますが、以前のアイテムに関連付けられたままとなります。次の更新日に延期されていた交換が行われると、新しいアイテムが返されます。
以前は、ProrationMode.DEFERRED
でこのユーザー エクスペリエンスを達成できましたが、ProrationMode.DEFERRED
は Play Billing Library 6 で非推奨になりました。動作の違いについては、次の表をご覧ください。
時刻 |
ProrationMode.DEFERRED(非推奨) |
ReplacementMode.DEFERRED |
購入フロー完了直後(アプリ) |
購入後、アップグレードまたはダウングレードが正常に処理されたかどうかを示すステータスとともに 以前のプランの利用資格は、次回の更新日まで継続されます。アプリで適切な利用資格を付与するため、 新しい購入トークンが表示されないため、この時点では処理できません。 |
購入後、アップグレードまたはダウングレードが正常に処理されたかどうかを示すステータスとともに
新しい購入トークンが表示されるため、交換が行われるタイミングを考慮して、この時点でトークンを処理する必要があります。 |
購入フロー完了直後(バックエンド) |
SUBSCRIPTION_PURCHASED RTDN は購入フロー後に送信されません。バックエンドはまだ新しい購入を認識しません。 |
購入フロー直後、新しい購入トークンについて、古い product_id が設定された SUBSCRIPTION_PURCHASED RTDN が送信されます。 新しい購入トークンを使用して purchases.subscriptionsv2.get メソッドを呼び出すと、購入時間を示す「startTime」と 2 つの項目を持つ購入が返されます。
以前の購入トークンについて SUBSCRIPTION_EXPIRED が送信されます。以前の購入トークンを使用して purchases.subscriptionsv2.get メソッドを呼び出すと、期限切れと表示されます(以前のプランの利用資格の残りの期間分は、新しい購入に移行されます)。 |
交換時 - 購入フロー後の初回更新(アプリ) |
新しい購入トークンが表示されたら、処理する必要があります。 |
新しい購入は、購入フロー完了時にすでに処理されているはずです。そのため、アプリでは、正しい利用資格が付与されていることを確認する以外、特別なアクションは行わないでください。 |
交換時 - 購入フロー後の初回更新(バックエンド) |
最初の SUBSCRIPTION_RENEWED RTDN が送信されると、新しい購入の処理と承認ができるようになります。 定期購入リソースの |
新しい購入トークンに対して SUBSCRIPTION_PURCHASED RTDN が送信され、「startTime」として記録された時点で、新規購入が処理、承認されました。 ReplacementMode.DEFERRED を使用すると、初回更新は他の更新の標準的な動作に従うため、このイベントが発生したときに交換のための特別なロジックを処理する必要はありません。 新しい購入トークンを使用して purchases.subscriptionsv2.get メソッドを呼び出すと、次の 2 つの項目を持つ購入が返されます。
|
非推奨の ProrationMode.DEFERRED の代わりに、今後は ReplacementMode.DEFERRED を使用してください。利用資格の変更に関して同じ動作を示す一方で、他の新しい購入の動作とより一貫性のある購入管理方法を提供します。
顧客管理
リアルタイム デベロッパー通知を使用すると、ユーザーの解約をリアルタイムに検出できます。定期購入が期限切れになる前にユーザーが解約した場合は、ユーザーにプッシュ通知またはアプリ内メッセージを送信して、再度定期購入するように促すことができます。
ユーザーが定期購入を解約した後、アプリ内または Play ストアでユーザーの再獲得を試みることができます。次の表に、さまざまな定期購入のシナリオ、および関連する再獲得のための操作とアプリの要件を示します。
サブスクリプションの有効期限前 | 定期購入の有効期限後 | |||
アプリ内 | Play ストア内 | アプリ内 | Play ストア内 | |
再獲得機能 | アプリ内定期購入 | 再開 | アプリ内定期購入 | 再度定期購入 |
ユーザーが購入手続きを行う | ○ | なし | ○ | ○ |
ユーザーの定期購入は同一の SKU に関連付けられた状態を保持する | ユーザーは同一または異なる SKU に登録できる | ○ | ユーザーは同一または異なる SKU に登録できる | ○ |
新しい購入トークンを作成する | ○ | なし | ○ | ○ |
デフォルトで有効 | なし | ○すべてのデベロッパーがサポートを必要とする | なし |
Billing Library 2.0 以降を使用しないアプリ: × Billing Library 2.0 以降を使用するアプリ: ○デベロッパーは Console でオプトアウトできる |
ユーザーに請求が行われた場合 |
同一の SKU を使用する場合: 現在の請求対象期間の終了 異なる SKU を使用する場合: 比例配分モードによって異なる |
現在の請求対象期間の終了 | すぐに | すぐに |
実装が必要 | アプリに再登録 UI を表示する |
定期購入のステータスの変化を検出する Play ストアへのディープリンク |
アプリに再登録 UI を表示する | アプリ外購入を処理する |
定期購入の有効期限前 - アプリ内
定期購入が解約済みであっても有効期限が切れていない場合は、新規の定期購入者と同じアプリ内のアイテム購入フローを適用すると、定期購入者はアプリ内で定期購入を再開できるようになります。UI がユーザーに既存の定期購入がある状態を反映していることを確認します。たとえば、ユーザーの現在の有効期限と再開価格とともに [再有効化] ボタンを表示することが考えられます。
ほとんどの場合は、次のように、ユーザーが定期購入に登録していた時点と同一の価格と SKU をユーザーに提示する必要があります。
- 同一の SKU で新規の定期購入の購入を開始します。
- 新しい定期購入は、以前の定期購入に代わって同じ有効期限で更新されます。古い定期購入は直ちに期限切れとしてマークされます。
- たとえば、あるユーザーが「Example Music App」というアプリを定期購入していたとします。定期購入の有効期限は 8 月 1 日です。7 月 10 日に、同じ月額で 1 か月分再度定期購入するとします。新しい定期購入は残りのクレジットに基づいて比例配分され、すぐに有効になり、8 月 1 日に更新されます。
別の価格(たとえば、新しい無料試用や再獲得割引)を提示する場合は、ユーザーに異なる SKU を提示できます。
- 交換モード
WITHOUT_PRORATION
を使用して、異なる SKU でアップグレードまたはダウングレードを開始します。 - 新しい定期購入は、以前の定期購入に代わって同じ有効期限で更新されます。元の有効期限日に、新しい SKU の価格(お試し価格を含む)がユーザーに課金されます。難読化されたアカウント ID を使用して以前の定期購入を作成した場合は、アップグレードとダウングレードのために同じ ID を
BillingFlowParams
に渡す必要があります。 - たとえば、あるユーザーが「Example Music App」というアプリを定期購入していたとします。定期購入の有効期限は 8 月 1 日です。7 月 10 日に、お試し価格で 1 年分再度定期購入するとします。新しい定期購入は直ちにアクティブになり、ユーザーに対して 8 月 1 日にお試し価格が請求されます。
- 無料試用またはお試し価格を再獲得用 SKU に含める場合は、Google Play Console で、アプリごとの無料試用を 1 回に制限する [Allow one free trial per app] チェックボックスをオフにして、ユーザーを対象に含めます。
購入トークンを受け取ったら、新しい定期購入の場合と同様に購入を処理します。さらに、Google Play Developer API は、定期購入リソース内で linkedPurchaseToken
を返します。サービスに対するアクセスに以前のトークンが使用されないように、linkedPurchaseToken
内で提供されるトークンは必ず無効にしてください。
定期購入の有効期限前 - Play ストア内
解約済みであっても定期購入が有効である間は、ユーザーは Google Play 定期購入センターで [再度定期購入](以前の [再開])をクリックすることで、定期購入を再開できます。それにより、同じ定期購入と購入トークンが維持されます。
![解約済みの定期購入が [再度定期購入] ボタンとともに表示された Google Play ストア アプリの [定期購入] セクション](https://developer.android.com/static/images/google/play/billing/resubscribe.jpg?authuser=7&hl=ja)
定期購入の再開の詳細については、再開をご覧ください。
定期購入の有効期限後 - アプリ内
有効期限が切れた定期購入者がアプリ内で再度定期購入できるようにするには、新規の定期購入者と同じアプリ内のアイテム購入フローを適用します。次の点にご注意ください。
- ユーザーに割引を適用するには、特別価格を設定した定期購入用のアイテム ID を提供する必要があります。これは再獲得用 SKU とも呼ばれます。この特典はアプリで提供することも、メールなどアプリ以外の方法でユーザーに通知することもできます。
- 再獲得用の定期購入を開始するには、Google Play Billing Library を使用して、Android アプリ内で購入フローを開始します。これは新しい定期購入と同じプロセスですが、デベロッパーは、ユーザーが利用できる SKU を決定できます。
- 無料試用またはお試し価格を再獲得用 SKU に含める場合は、Google Play Console で、アプリごとの無料試用を 1 回に制限する [Allow one free trial per app] チェックボックスをオフにして、ユーザーを対象に含めます。
- 同じ SKU に再登録した場合、ユーザーは無料試用期間やお試し価格の対象ではなくなります。UI がこれを反映していることを確認します。
購入トークンを受け取ったら、新しい定期購入の場合と同様に購入を処理します。定期購入リソースで linkedPurchaseToken
を受け取ることはありません。
定期購入の有効期限後 - Play ストア内
再登録が有効になっている場合、ユーザーは Google Play 定期購入センターで [再度定期購入] をクリックすることで、有効期限から最長 1 年間同じ SKU に再登録できます。それにより、新しい定期購入と購入トークンが生成されます。
![解約済みと期限切れの定期購入が [再度定期購入] ボタンおよび [削除] ボタンとともに表示された Google Play ストア アプリの [定期購入] セクション](https://developer.android.com/static/images/google/play/billing/resubscribe-remove.jpg?authuser=7&hl=ja)
再度定期購入はアプリ外での購入と見なされるため、アプリ外で行われた購入の処理のおすすめの方法を実施してください。
定期購入を宣伝する
プロモーション コードを作成して、既存の定期購入の無料試用の延長特典を特定のユーザーに提供できます。詳細については、プロモーション コードをご覧ください。
無料試用の場合、Google Play は、無料試用期間が始まる前に、ユーザーが有効な支払い方法を設定しているかどうかを確認します。ユーザーによっては、この確認が支払い方法に対する保留または請求として表示されることがあります。この保留または請求は一時的なものであり、後で取り消されるか払い戻されます。
試用期間後は、ユーザーのお支払い方法に対して正規の定期購入価格が請求されます。
ユーザーが無料試用中に定期購入を解約した場合、試用期間が終了するまで定期購入は継続され、無料試用期間が終了しても請求は発生しません。
解約、払い戻し、取り消し
Google Play Developer API を使用して、定期購入の解約、払い戻し、取り消しができます。この機能は Google Play Console でも利用できます。
- 解約: ユーザーは Google Play で定期購入を解約できます。アプリまたはウェブサイトでユーザーが解約できるオプションを用意することもできます。アプリでは解約の説明に沿って、これらの解約を処理する必要があります。
- 払い戻し: 払い戻しを行った後も、ユーザーは引き続き定期購入を利用できます。払い戻しは、たとえば、技術的なエラーによってユーザーがアイテムにアクセスできなかったものの、エラーが解決された場合に行うことができます。最新のお支払い額を超える金額を払い戻す場合、または一部払い戻しを行う場合は、Google Play Console を使用する必要があります。
- 取り消し: 取り消しを行うと、ユーザーは直ちに定期購入を利用できなくなります。取り消しは、たとえば、技術的なエラーによってユーザーがアイテムにアクセスできなくなり、ユーザーがアイテムを使用し続けることを望まない場合に行うことができます。アプリでは取り消しの説明に沿って、これらの解約を処理する必要があります。
次の表に、解約、払い戻し、取り消しの違いを示します。
更新を停止する | 料金を払い戻す | アクセス権を取り消す | |
解約 | ○ | × | なし |
払い戻し | なし | ○ | なし |
取り消し | ○ | ○ | はい |
定期購入者の課金を延期する
Google Play Developer API の Purchases.subscriptions:defer
を使用すると、自動更新される定期購入の次回の課金日を延期できます。延期期間中、ユーザーは完全なアクセス権で定期購入コンテンツを利用できますが、課金はされません。定期購入の更新日は、新しい日付で更新されます。
プリペイド プランでは、defer billing API を使用して有効期限を延期できます。
課金を延期することで、次のことが可能になります。
- 特別優待の一環として、映画の購入について 1 週間の無料期間を設けるなど、無料アクセス権を付与する。
- 感謝の印としてユーザーに無料アクセス権を付与する。
課金の延期は、API 呼び出し 1 回あたり最短で 1 日、最長で 1 年間です。課金をさらに延期するには、次回の課金日の前に再度 API を呼び出します。
たとえば、あるユーザーが「Fishing Quarterly」というアプリのオンライン コンテンツを月次定期購入しているとします。普段は毎月 1 日に、125 円を支払っています。3 月に、アプリ パブリッシャーが実施したオンライン調査に回答しました。パブリッシャーは、謝礼として 6 週間分を無料にし、次の支払いを 5 月 15 日(予定されていた次回課金日 4 月 1 日の 6 週間後)まで延期することにしました。このユーザーは 4 月 1 日と 5 月 1 日には課金されませんが、通常どおりコンテンツにアクセスできます。5 月 15 日に、通常どおりの 125 円が定期購入料金として課金されます。次回の更新日は 6 月 15 日です。
延期した場合は、メールまたはアプリ内で請求日が変更されたことをユーザーに通知することもできます。
支払い方法の不承認を処理する
定期購入の更新でお支払いの問題が発生した場合、Google は解約までの一定の期間、定期購入の更新を定期的に試みます。この復元期間は猶予期間と重複します。復元期間が終了すると、アカウントの一時停止期間に移行します。この間、Google はお支払い方法を更新するよう促すメールと通知をユーザーに送信します。
猶予期間が設定されていれば、お支払い方法が不承認となった時点で定期購入は猶予期間に入ります。猶予期間中も、ユーザーが定期購入の利用資格に引き続きアクセスできるようにする必要があります。
猶予期間が終了すると、定期購入はアカウントの一時停止期間に入ります。アカウントの一時停止中は、ユーザーが定期購入の利用資格にアクセスできないようにする必要があります。
Google Play Console で、自動更新の基本プランの猶予期間とアカウントの一時停止期間をそれぞれ指定できます。デフォルトの設定よりも短い期間を指定すると、支払いの不承認から復元される定期購入の数が少なくなる可能性があります。
お支払い方法が不承認となっている間に定期購入が再開される可能性を最大限に高めるよう、お支払いに関する問題があることをユーザーに伝えて修正を求めることができます。
これは、猶予期間とアカウントの一時停止のセクションに記載されているように、デベロッパー自身で行えます。また、In-App Messaging API を実装し、Google がアプリでユーザーにメッセージを表示することもできます。
アプリ内メッセージング
InAppMessageCategoryId.TRANSACTIONAL
で In-App Messaging を有効にした場合は、Google Play が猶予期間とアカウントの一時停止期間中に 1 日に 1 回、ユーザーにメッセージを表示し、アプリを終了せずにお支払い方法を修正する機会をユーザーに提供します。
![お支払い方法を修正するようユーザーに伝えるスナックバー](https://developer.android.com/static/images/google/play/billing/subscriptions-in-app-messaging-snackbar.png?authuser=7&hl=ja)
ユーザーがアプリを開くたびにこの API を呼び出し、メッセージを表示するかどうかを指定することをおすすめします。
ユーザーが定期購入を再開すると、SUBSCRIPTION_STATUS_UPDATED
のレスポンス コードが購入トークンと一緒に返されます。この購入トークンを使用して Google Play Developer API を呼び出し、アプリで定期購入のステータスを更新します。
In-App Messaging を統合する
アプリ内メッセージをユーザーに表示するには、BillingClient.showInAppMessages()
を使用します。
以下に、In-App Messaging のフローをトリガーする例を示します。
Kotlin
val inAppMessageParams = InAppMessageParams.newBuilder() .addInAppMessageCategoryToShow(InAppMessageCategoryId.TRANSACTIONAL) .build() billingClient.showInAppMessages(activity, inAppMessageParams, object : InAppMessageResponseListener() { override fun onInAppMessageResponse(inAppMessageResult: InAppMessageResult) { if (inAppMessageResult.responseCode == InAppMessageResponseCode.NO_ACTION_NEEDED) { // The flow has finished and there is no action needed from developers. } else if (inAppMessageResult.responseCode == InAppMessageResponseCode.SUBSCRIPTION_STATUS_UPDATED) { // The subscription status changed. For example, a subscription // has been recovered from a suspend state. Developers should // expect the purchase token to be returned with this response // code and use the purchase token with the Google Play // Developer API. } } })
Java
InAppMessageParams inAppMessageParams = InAppMessageParams.newBuilder() .addInAppMessageCategoryToShow(InAppMessageCategoryId.TRANSACTIONAL) .build(); billingClient.showInAppMessages(activity, inAppMessageParams, new InAppMessageResponseListener() { @Override public void onInAppMessageResponse(InAppMessageResult inAppMessageResult) { if (inAppMessageResult.responseCode == InAppMessageResponseCode.NO_ACTION_NEEDED) { // The flow has finished and there is no action needed from developers. } else if (inAppMessageResult.responseCode == InAppMessageResponseCode.SUBSCRIPTION_STATUS_UPDATED) { // The subscription status changed. For example, a subscription // has been recovered from a suspend state. Developers should // expect the purchase token to be returned with this response // code and use the purchase token with the Google Play // Developer API. } } });
定期購入の保留中の取引を処理する
保留中の取引は、初回購入、チャージ、アップグレード、ダウングレードで発生する可能性があります。定期購入は SUBSCRIPTION_STATE_PENDING
ステータスで開始し、その後 SUBSCRIPTION_STATE_ACTIVE
に移行します。取引が期限切れになるか、ユーザーによってキャンセルされると、SUBSCRIPTION_STATE_PENDING_PURCHASE_EXPIRED
に移行します。ユーザーの利用資格の更新は、取引の完了後に行う必要があります。
保留中の取引がある初回購入の定期購入ステータスの変更は簡単です。ユーザーが保留中の取引を開始すると、アプリは PENDING
状態の Purchase
を受け取ります。トランザクションが完了すると、アプリは Purchase
を再度受け取り、状態が PURCHASED
に更新されます。タイプ SUBSCRIPTION_PURCHASED
の SubscriptionNotification
メッセージが RTDN クライアントに送信されます。通常のプロセスに沿って購入を確認し、ユーザーにコンテンツへのアクセス権を付与して、購入を承認します。トランザクションが期限切れになるかキャンセルされると、タイプ SUBSCRIPTION_PENDING_PURCHASE_CANCELED
の SubscriptionNotification
メッセージが RTDN クライアントに送信されます。このような場合、ユーザーがコンテンツにアクセスできないようにする必要があります。
保留中のトランザクションがあるチャージ、アップグレード、ダウングレードには、元の定期購入と新しい定期購入の両方の状態変化が伴います。ユーザーが保留中のチャージ、アップグレード、ダウングレードの取引を開始すると、アプリは PendingPurchaseUpdate
オブジェクトとともに、古い定期購入の Purchase
を受け取ります。この時点では、ユーザーは以前の定期購入を所有しており、新しい定期購入はまだ取得していません。PendingPurchaseUpdate
オブジェクトで getProducts()
と getPurchaseToken()
を呼び出すと、新しい定期購入の商品 ID と購入トークンが返されます。取引が完了すると、アプリは Purchase
を受け取ります。このとき、新しい定期購入用のトップレベルの購入トークンが設定され、ステータスが PURCHASED
に設定されます。タイプ SUBSCRIPTION_PURCHASED
の SubscriptionNotification
メッセージが RTDN クライアントに送信されます。今回に限り、古い購入トークンを新しい購入トークンに置き換えて、コンテンツへのユーザーのアクセス権を更新する必要があります。トランザクションが期限切れになるかキャンセルされると、タイプ SUBSCRIPTION_PENDING_PURCHASE_CANCELED
の SubscriptionNotification
メッセージが RTDN クライアントに送信されます。そのような場合、ユーザーは以前の定期購入のコンテンツに引き続きアクセスできます。