Google
PR

【Google】アプリ内課金の1回限りの購入ライフサイクル

saratogax
記事内に商品プロモーションを含む場合があります

Google Play のアプリ内課金のうち、「1回限りの購入(都度課金)」は、購入のたびに完結するタイプの商品です。

定期購入に比べるとライフサイクルはシンプルですが、消費(consume)や承認(acknowledge)の扱いには注意が必要です。

このページでは、1回限りの購入のライフサイクルと、バックエンドでの処理方法をまとめていきます。

アプリ内課金全体の中での位置づけは、以下のまとめページもあわせてご覧ください。

あわせて読みたい
【Google】アプリ内課金(Google Play Billing)の全体像と記事まとめ
【Google】アプリ内課金(Google Play Billing)の全体像と記事まとめ

1回限りの購入のライフサイクル

1回限りの購入は、定期購入のように更新や猶予期間といった状態を持ちません。

公式ドキュメントでは、購入処理の流れがおおよそ次のように整理されています。

  1. 購入できる商品をユーザーに提示する
  2. 購入フローを起動し、ユーザーに購入してもらう
  3. サーバー(バックエンド)で購入を検証する
  4. ユーザーにコンテンツを提供する
  5. コンテンツの提供を承認(acknowledge)する。消費型の商品は、再購入できるように消費(consume)する

シンプルに見えますが、消費型か非消費型か、購入が確定済みか保留中かによって、処理を分ける必要があります。

消費型と非消費型

1回限りの購入の商品は、消費型(consumable)と非消費型(non-consumable)の 2 種類に分かれます。

種類特徴購入後の処理
消費型繰り返し購入できる(コイン・ジェム・一時的なアイテムなど)消費(consume)する
非消費型1 ユーザーにつき 1 回だけ購入できる(永続機能・プレミアムコンテンツなど)承認(acknowledge)する
※表は横スクロールできます

消費型は、消費するとそのトークンが再購入できる状態に戻ります。

非消費型は消費せず、承認だけを行います。

購入状態(PurchaseState)の確認

購入を処理する前に、その購入が「支払い済み」なのか「保留中」なのかを確認します。

Google Play Billing Library の購入状態(PurchaseState)には、次の 3 つの値があります。

状態内容
PURCHASED支払いが完了し、購入を処理できる状態。コンテンツの提供はこの状態のときだけ行う
PENDING支払い完了までに追加の手順が必要な状態。この状態ではコンテンツを提供しない
UNSPECIFIED_STATE状態が不明、または未初期化
※表は横スクロールできます

大切なのは、コンテンツの提供や承認は PURCHASED のときだけ行うという点です。

PENDING の購入に対してコンテンツを提供してしまうと、支払いが完了しないまま権利を渡すことになってしまいます。

PurchaseState の数値は、読み取る場所で割り当てが異なる点に注意が必要です。Billing Library の getPurchaseState() は 0=UNSPECIFIED_STATE・1=PURCHASED・2=PENDING ですが、購入情報の JSON や Developer API の purchaseState はこれとは別の体系になっています。公式は、アプリ側では getPurchaseState() を使うよう案内しています。

承認(acknowledge)と消費(consume)

コンテンツを提供したら、購入を処理したことを Google に伝える必要があります。

非消費型の商品は承認(acknowledge)、消費型の商品は消費(consume)を行います。

消費は承認も兼ねるため、消費型の商品で別途 acknowledge を呼ぶ必要はありません。

購入を 3 日以内に承認(または消費)しないと、ユーザーは自動的に払い戻しを受け、Google Play は購入を取り消します。なお、この 3 日間のカウントは、購入状態が PENDING から PURCHASED に変わったときから始まります。

処理が重複しないよう、承認の前には isAcknowledged() で承認済みかどうかを確認しておくと安心です。

保留中の購入(PENDING)

保留中の購入とは、ユーザーが購入を開始してから、実際に支払いが処理されるまでに追加の手順が必要な購入のことです。

たとえば、コンビニなどの実店舗で後から現金で支払うケースがこれにあたります。

この場合、ユーザーは受け取ったコードを店舗で提示して支払い、支払いが完了すると Google から通知が届きます。

アプリは、保留中の購入をサポートする必要があります。

具体的には、BillingClient の生成時に enablePendingPurchases() を呼び出します。

支払いが完了すると購入状態が PURCHASED に変わり、キャンセルされた場合は後述の ONE_TIME_PRODUCT_CANCELED 通知が届きます。

なお、PENDING の購入では orderId が null になり、PURCHASED に変わったときに値が入ります。

orderId が入っている前提で検証していると、保留中の購入で想定外の挙動になりやすいので注意が必要です。

RTDN での通知

1回限りの購入も、リアルタイムデベロッパー通知(RTDN)で状態変化を受け取れます。

ユーザーが購入またはキャンセルすると、Google Play は OneTimeProductNotification を送信します。

  • ONE_TIME_PRODUCT_PURCHASED … 1回限りの商品が購入された
  • ONE_TIME_PRODUCT_CANCELED … 保留中だった購入がキャンセルされた

ただし、1回限りの購入の RTDN は、Google Play Console で対象の通知を有効にしていないと送信されません。

RTDN の設定方法や通知データの構造は、以下のページで解説しています。

あわせて読みたい
【Google】リアルタイムデベロッパー通知(RTDN)の仕組みと設定
【Google】リアルタイムデベロッパー通知(RTDN)の仕組みと設定

バックエンドでの処理

セキュリティ上の理由から、購入の検証と処理はバックエンドで行うことが推奨されています。

バックエンドでは、Google Play Developer API の purchases.products.get を使い、購入トークンから最新の状態を取得します。

処理の重複を防ぐため、取得した結果のフィールドを確認しておきましょう。

  • 消費型 … consumptionState で、すでに消費済みでないかを確認する
  • 非消費型 … acknowledgementState で、すでに承認済みでないかを確認する

消費型の商品をバックエンドで確実に消費したい場合は、purchases.products.consume を使う方法もあります。

また、同じ購入を二重に処理しないよう、購入トークン(purchaseToken)を一意キーとして、既存の購入と重複していないかを確認します。

orderId はプロモーションコードを使った購入などでは生成されないため、重複チェックや主キーには使わないよう公式に推奨されています。

まとめ

Google のアプリ内課金における「1回限りの購入」のライフサイクルを紹介してきました。

定期購入よりは状態がシンプルですが、消費型か非消費型か、PURCHASED か PENDING かによって処理が変わる点は押さえておきたいところです。

とくに、3 日以内の承認・消費を忘れると購入が自動で取り消されてしまうので、バックエンドでの処理フローはしっかり組んでおきましょう。

参考(出典)

ABOUT ME
saratoga
saratoga
フリーランスエンジニア
仕事にも趣味にも IT を駆使するフリーランスエンジニア。技術的な TIPS や日々の生活の中で深堀りしてみたくなったことを備忘録として残していきます。
記事URLをコピーしました