Google Play Billing Library(以下PBL)は、Androidアプリでアプリ内課金と定期購入を扱うGoogle公式のライブラリです。2026年10月13日時点の最新版は9.1.0(2026年6月18日公開)で、版7は2026年8月31日に新規アプリと更新で使えなくなりました。
この記事では、9.1.0でビルドが通ることを確かめたKotlinコードを軸に、導入から購入・承認・サーバー検証・テストまでを順に説明します。あわせて、8.0と9.0で実際に消えたAPIを配布物(AAR)から抜き出した結果と、2026年9月30日に切り替わった日本の手数料も載せています。
まとめ:Google Play Billing Libraryの最新版と実装の要点
- 最新版:9.1.0(2026年6月18日)。依存関係は
com.android.billingclient:billing:9.1.0。minSdkは23。 - 期限:2026年8月31日から新規・更新には版8以上が必要(延長申請で2026年11月1日まで)。版8の期限は2027年8月31日、版9は2028年8月31日。
- 削除されたAPI:8.0で
querySkuDetailsAsync・queryPurchaseHistoryAsync・引数なしenablePendingPurchases()が、9.0でSkuDetailsなどSKU系のクラスそのものが消えた。古いコードは版を上げた時点でコンパイルが通らない。 - 実装の軸:
enablePendingPurchases(PendingPurchasesParams)とenableAutoServiceReconnection()を付けて接続し、queryProductDetailsAsyncで商品を取り、launchBillingFlowで購入する。 - 購入後:承認が必要な購入は原則3日以内に承認(消費)しないと自動で払い戻される。1週間未満の前払い式定期購入はプラン期間の半分以内が期限。付与前にサーバーで
subscriptionsv2/productsv2を使って検証し、状態の変化はRTDNで受ける。 - 日本の手数料:2026年9月30日から新体系。Google Play Billing経由なら定期購入は10%+決済手数料5%、一回限りの商品は新規インストール20%・既存インストール25%に5%が加わる。
Google Play Billing Libraryの役割と最新バージョン
PBLはアプリと端末上のPlayストアをつなぐクライアント側の部品です。商品情報の取得、購入画面の表示、購入結果の受け取り、承認と消費までを担います。購入の正当性の確認や定期購入の更新・解約の追跡は、サーバー側のGoogle Play Developer APIとリアルタイムデベロッパー通知(RTDN)の役目です。PBLだけで課金が完結するわけではない点を最初に押さえておくと、後の設計で迷いません。
PBLが扱う商品の種類と処理の範囲
扱える商品は、一回限りの商品(8.0.0で「アプリ内アイテム」から呼び名が変わった)と定期購入の2種類です。一回限りの商品は、コインのように何度も買える消費型と、広告非表示のように一度買えば済む非消費型に分かれます。定期購入は基本プランとオファーの組み合わせで売り、購入時には選んだオファーの offerToken を渡します。8.0.0からは一回限りの商品にも複数の購入オプションとオファーを設定できるようになりました。
9.1.0のAARに含まれるマニフェストには、com.android.vending.BILLING 権限と、PBLの版を示す com.google.android.play.billingclient.version のメタデータが入っています。アプリ側で権限を書き足す必要はありません。
リリース履歴:7.0から9.1までの変更点
直近の版と主な変更は次のとおりです。日付と内容は公式リリースノートに基づきます。
| 版 | 公開日 | 主な変更 |
|---|---|---|
| 9.1.0 | 2026-06-18 | Billing Choice用のAPI(getBillingChoiceInfoAsync など) |
| 9.0.0 | 2026-05-19 | Playストア遮断時の応答がBILLING_UNAVAILABLEに |
| 8.3.0 | 2025-12-23 | 外部決済(EXTERNAL_PAYMENTS)用のAPI |
| 8.2.0/8.2.1 | 2025-12-09/12-15 | 外部リンク・外部オファー用API、旧APIを非推奨に |
| 8.1.0 | 2025-11-06 | 一時停止中の定期購入の取得、minSdkを23へ |
| 8.0.0 | 2025-06-30 | 自動再接続、サブ応答コード、旧API削除 |
| 7.0.0 | 2024-05-14 | 分割払い定期購入、PendingPurchasesParams |
9.0.0では、ほかに外部決済の DeveloperProvidedBillingDetails.getLinkUri() が @Nullable になり、ライブラリのtargetSdkVersionが35に上がり、オプトイン型の値上げをアプリ内メッセージで知らせられるようになりました。8.2.0以降と9.1.0で増えたAPIの多くは、外部決済や決済方法の選択プログラムに参加するアプリ向けで、Google Play Billingだけで売るアプリは使わなくて構いません。
v8以上が必須になった2026年8月31日以降の対応
PBLはメジャーバージョンごとに約2年の非推奨化サイクルがあり、新規アプリ・更新で使える期限が定められています。公式の非推奨化FAQが示す期限は次のとおりです。
| 版 | 新規・更新の期限 | 延長申請の期限 |
|---|---|---|
| 5 | 2024-08-31 | 2024-11-01 |
| 6 | 2025-08-31 | 2025-11-01 |
| 7 | 2026-08-31 | 2026-11-01 |
| 8 | 2027-08-31 | 2027-11-01 |
| 9 | 2028-08-31 | 2028-11-01 |
期限を過ぎても、すでに配信中のアプリが止まるわけではありません。止まるのは古い版を含む新規アプリと更新の公開です。版7のまま更新を出そうとするとPlay Consoleに「バージョン8.0.0以降を使用する必要がある」旨の警告が出て、[ポリシーのステータス]の警告詳細から延長申請フォームを開けます。延長しても2026年11月1日までなので、申請は移行作業の時間を稼ぐ手段にとどまります。
自分のアプリが実際にどの版を含んでいるかは、build.gradle の記述ではなく依存ツリーで確かめます。課金系のSDKやゲームエンジンのプラグインが古いPBLを推移的に持ち込んでいることがあるためです。
# 依存ツリーから実際に解決された版を確かめる(推移的依存で古い版が入っていないかも見る)
./gradlew :app:dependencies --configuration releaseRuntimeClasspath | grep billingclient
ビルド済みのAPKなら、Android StudioのAPK Analyzerでマージ後の AndroidManifest.xml を開き、com.google.android.play.billingclient.version の値を見れば分かります。
依存関係の追加とBillingClientの初期化
アプリの build.gradle.kts に次を足します。KTX版はコルーチン用の拡張関数を含み、Javaで書くなら不要です。
dependencies {
val billingVersion = "9.1.0"
implementation("com.android.billingclient:billing:$billingVersion")
// コルーチン(suspend関数)で書く場合は KTX 版を使う
implementation("com.android.billingclient:billing-ktx:$billingVersion")
}
次のコードは、Kotlin 2.4.21のコンパイラで、9.1.0のAAR(classes.jar)とAndroid 15(API 35)の android.jar を参照してエラーなくコンパイルできたクラスの前半です。後半の商品取得と購入は次の章に載せています。
import android.app.Activity
import android.content.Context
import com.android.billingclient.api.*
import com.android.billingclient.api.BillingClient.BillingResponseCode
import com.android.billingclient.api.BillingClient.ProductType
class BillingManager(context: Context, private val sendToServer: (Purchase) -> Unit) {
private val purchasesUpdatedListener = PurchasesUpdatedListener { result, purchases ->
when (result.responseCode) {
BillingResponseCode.OK -> purchases?.forEach { handlePurchase(it) }
BillingResponseCode.USER_CANCELED -> Unit
else -> when (result.onPurchasesUpdatedSubResponseCode) {
BillingClient.OnPurchasesUpdatedSubResponseCode.PAYMENT_DECLINED_DUE_TO_INSUFFICIENT_FUNDS ->
Unit // 支払い方法の変更を案内する
else -> Unit // result.debugMessage をログに残す
}
}
}
private val billingClient = BillingClient.newBuilder(context)
.setListener(purchasesUpdatedListener)
.enablePendingPurchases(
PendingPurchasesParams.newBuilder().enableOneTimeProducts().build()
)
.enableAutoServiceReconnection()
.build()
fun connect(onReady: () -> Unit) {
billingClient.startConnection(object : BillingClientStateListener {
override fun onBillingSetupFinished(result: BillingResult) {
if (result.responseCode == BillingResponseCode.OK) onReady()
}
override fun onBillingServiceDisconnected() {
// 自動再接続を有効にしているので startConnection() は呼ばない
}
})
}
// 商品の取得・購入・復元は次のコードに続く
押さえるべき点は2つです。1つ目は enablePendingPurchases の引数で、enableOneTimeProducts() を付けない PendingPurchasesParams を渡すと、コンパイルは通るものの、実行時に build() が「Pending purchases for one-time products must be supported.」という IllegalArgumentException を投げます(9.1.0のクラスファイルを javap -c で確認)。前払い式の定期購入でも保留中の取引を扱うなら enablePrepaidPlans() を追加します。2つ目は、引数なしの enablePendingPurchases() が8.0.0で削除されたことで、7系の書き方のままだとこの行でコンパイルが落ちます。
enableAutoServiceReconnectionによる自動再接続
enableAutoServiceReconnection() は8.0.0で入ったオプトインのメソッドで、接続が切れた状態でAPIを呼ぶと、呼び出しの前にライブラリが接続を張り直します。公式の統合ガイドは、これを有効にしたら onBillingServiceDisconnected() の中で startConnection() を呼ばず、空にするかログやUI更新だけに使うよう求めています。自前の再接続ループと併用すると二重に接続を試みるので、どちらか一方に寄せてください。
商品取得から購入フローまでの実装(Kotlin)
前章のクラスの続きです。コンパイルは確認済みですが、購入フローの実機動作を保証するものではありません。この例は先頭の定期購入オファーを使用するため、複数プランを表示する実装では、ユーザーが選んだオファーのトークンをlaunchに渡す形へ変更します。
// BillingManager クラスの続き
fun querySubscription(productId: String, onResult: (ProductDetails?) -> Unit) {
val params = QueryProductDetailsParams.newBuilder()
.setProductList(listOf(
QueryProductDetailsParams.Product.newBuilder()
.setProductId(productId)
.setProductType(ProductType.SUBS)
.build()
))
.build()
billingClient.queryProductDetailsAsync(params) { result, queryResult ->
if (result.responseCode != BillingResponseCode.OK) return@queryProductDetailsAsync onResult(null)
queryResult.unfetchedProductList.forEach { /* it.productId と it.statusCode をログに残す */ }
onResult(queryResult.productDetailsList.firstOrNull())
}
}
fun launch(activity: Activity, details: ProductDetails, hashedUserId: String): BillingResult? {
val offerToken = details.subscriptionOfferDetails?.firstOrNull()?.offerToken ?: return null
val flowParams = BillingFlowParams.newBuilder()
.setProductDetailsParamsList(listOf(
BillingFlowParams.ProductDetailsParams.newBuilder()
.setProductDetails(details)
.setOfferToken(offerToken)
.build()
))
.setObfuscatedAccountId(hashedUserId)
.build()
return billingClient.launchBillingFlow(activity, flowParams)
}
private fun handlePurchase(purchase: Purchase) {
if (purchase.purchaseState != Purchase.PurchaseState.PURCHASED) return // PENDING は付与しない
sendToServer(purchase) // サーバーで検証・権利同期し、未承認なら承認する
}
// 接続完了後とonResume時に呼び、結果をサーバーで検証して権利を同期する
fun restore(onResult: (List<Purchase>) -> Unit) {
val params = QueryPurchasesParams.newBuilder().setProductType(ProductType.SUBS).build()
billingClient.queryPurchasesAsync(params) { result, purchases ->
if (result.responseCode == BillingResponseCode.OK) onResult(purchases)
}
}
}
queryProductDetailsAsyncの取得成功・失敗商品の返却
8.0.0から、ProductDetailsResponseListener は商品のリストではなく QueryProductDetailsResult を受け取ります。取れた商品は productDetailsList、取れなかった商品は unfetchedProductList に入り、後者は UnfetchedProduct ごとに商品IDとステータスコードを持ちます。「商品が表示されない」不具合の調査では、まずこのリストをログに出すのが近道です。商品IDの綴り違いや、Play Consoleで商品が有効になっていない場合はここに現れます。
launchBillingFlowへのofferTokenと難読化ユーザーIDの指定
定期購入では、subscriptionOfferDetails から選んだオファーの offerToken を setOfferToken に渡します。無料トライアル付きの月額プランと年額プランを並べるなら、ユーザーが選んだ方のトークンを渡す設計にします。setObfuscatedAccountId には自社のユーザーIDをハッシュ化した値を入れます。公式のセキュリティガイドは、Googleがこれを不正検知に使うことと、サーバー検証時に購入と自社アカウントの対応を照合するよう書いています。メールアドレスなどの個人情報をそのまま入れてはいけません。
応答コードとサブ応答コードの読み分け
BillingResult.responseCode の値は、9.1.0のクラスファイルから読み出すと次のとおりです。
| 定数 | 値 | 主な原因と対処 |
|---|---|---|
| OK | 0 | 成功 |
| USER_CANCELED | 1 | 購入画面を閉じた。再試行しない |
| SERVICE_UNAVAILABLE | 2 | 通信の一時的な失敗。間隔を空けて再試行 |
| BILLING_UNAVAILABLE | 3 | 端末やアカウントで課金できない |
| ITEM_UNAVAILABLE | 4 | 商品が無効か、その国で買えない |
| DEVELOPER_ERROR | 5 | 引数の誤り(offerTokenの渡し忘れ等) |
| ERROR | 6 | 上記以外の失敗。debugMessageを記録 |
| ITEM_ALREADY_OWNED | 7 | 対象商品・定期購入を所有済み |
| ITEM_NOT_OWNED | 8 | 持っていない商品を消費しようとした |
| NETWORK_ERROR | 12 | ネットワーク障害 |
| SERVICE_DISCONNECTED | -1 | 接続が切れている |
| FEATURE_NOT_SUPPORTED | -2 | 端末のPlayストアが機能に未対応 |
| SERVICE_TIMEOUT | -3 | 非推奨(9.1.0でも定数は残る) |
9.0.0から、キッズモードのように端末側でPlayストアが遮断されているときの応答は ERROR から BILLING_UNAVAILABLE に変わりました。この判定にはAndroidX Coreの1.9以降が必要です。8.3.0からは、外部決済の途中で離脱した取引も ERROR ではなく USER_CANCELED で返ります。エラーの種類で画面の文言を切り替えている場合は、版を上げたときに分岐が変わる点に注意してください。
ITEM_ALREADY_OWNED は、ユーザーがその商品や定期購入をすでに所有しているときに返ります。消費型を消費し忘れているのが原因のことも多いので、まず queryPurchasesAsync で所有状態を取り直します。消費型の未消費購入は検証・付与後に消費し、所有済みの非消費型や定期購入は重ねて購入させません。承認だけでは所有状態は解除されません。8.0.0以降は launchBillingFlow の結果にサブ応答コードも付き、残高不足なら PAYMENT_DECLINED_DUE_TO_INSUFFICIENT_FUNDS、オファーの対象外なら USER_INELIGIBLE が返ります。
購入後の処理:承認・消費とサーバー検証
購入が成功したら、検証してから権利を付与し、最後にGoogleへ処理済みを伝えます。この順番を崩すと、不正な購入トークンに権利を与えたり、正しい購入が自動で払い戻されたりします。
3日以内の承認と消費
購入の承認期限は原則3日で、未承認のまま期限を過ぎると自動払い戻しと権利取消の対象になります。ただし、1週間未満の前払い式定期購入はプラン期間の半分以内に承認する必要があります。保留中(PENDING)の購入は、PURCHASEDに変わった時点から3日を数えるので、期限は購入開始時ではなく支払いの確定時から管理します。非消費型と定期購入の初回購入は承認、消費型は消費で、消費は承認を兼ねます。自動更新定期購入の更新分は承認不要ですが、前払い式定期購入の追加購入は承認が必要です。バックエンドがあるなら、消費もサーバーからPlay Developer APIで行うのが公式の推奨です。
保留中の購入はコンビニ払いのように後から支払いが確定する取引で、この段階では権利を付与しません。上のコードの handlePurchase がPURCHASED以外で処理を抜けているのはそのためです。
Play Developer APIでの検証エンドポイント
サーバー側の検証と承認には次のエンドポイントを使います。パスはいずれも androidpublisher/v3/applications/{packageName}/purchases/ の下で、{id} は商品IDです。
| 用途 | HTTP | パス(purchases以下) |
|---|---|---|
| 一回限りの商品の状態取得 | GET | productsv2/tokens/{token} |
| 一回限りの商品の承認 | POST | products/{id}/tokens/{token}:acknowledge |
| 一回限りの商品の消費 | POST | products/{id}/tokens/{token}:consume |
| 定期購入の状態取得 | GET | subscriptionsv2/tokens/{token} |
| 定期購入の承認 | POST | subscriptions/{id}/tokens/{token}:acknowledge |
| 払い戻し・取消の一覧 | GET | voidedpurchases |
この表は、2026年10月12日版のGoogle Play Developer APIのディスカバリ文書から purchases 配下のメソッドを抜き出したものです。この版の文書には旧来の purchases.subscriptions.get が載っておらず、定期購入の状態取得は subscriptionsv2.get を使います。Play Developer APIの廃止予定一覧によると、subscriptions.get は2025年5月21日に非推奨となり、2027年8月31日に停止します(延長申請は2027年11月1日まで)。2026年7月1日より後に出たクライアントライブラリには含まれないため、ライブラリを更新すると該当メソッドそのものが無くなります。既存のライブラリなら停止日まで呼べますが、今のうちに subscriptionsv2.get へ移しておくのが安全です。
curl -H "Authorization: Bearer $ACCESS_TOKEN" \
"https://androidpublisher.googleapis.com/androidpublisher/v3/applications/com.example.app/purchases/subscriptionsv2/tokens/$PURCHASE_TOKEN"
端末の改ざんや非正規のアプリからのリクエストまで弾きたいなら、Play Integrity APIを併用します。Play Integrity APIの概要によると、既定の上限は全インストール合計で1日10,000リクエストで、引き上げは申請制です。Firebaseを使っているなら、Firebase App CheckでPlay Integrityをプロバイダにする構成がまとめやすいでしょう。
RTDNによる定期購入の状態変化の通知
定期購入の更新・猶予期間・アカウント保留・解約は、アプリが起動していなくても起きます。これを追うのがRTDNで、Cloud Pub/Subのトピックにbase64でエンコードされたJSONが届きます。RTDNのリファレンスによると、定期購入の通知は SUBSCRIPTION_PURCHASED(4)、SUBSCRIPTION_RENEWED(2)、SUBSCRIPTION_IN_GRACE_PERIOD(6)、SUBSCRIPTION_ON_HOLD(5)、SUBSCRIPTION_CANCELED(3)、SUBSCRIPTION_EXPIRED(13)などの種類を持ちます。
通知が伝えるのは「状態が変わった」ことだけです。受け取ったら必ず subscriptionsv2.get で最新の状態を取り直し、それを自社のデータベースに反映します。同じ通知が二度届くこともあるので、messageId で重複を弾きます。重複処理の作り方は冪等キーの発行・保存・再生の実装と同じ考え方で組めます。
旧コードを8・9へ上げるときに壊れる箇所(AARの実測)
9.0.0のリリースノートには、削除されたAPIの記載がありません。一方でPBL 9への移行ガイドは「以前に非推奨だったAPIを削除した」として一覧を載せています。どちらが実態に近いかを確かめるため、Googleのリポジトリから7.1.1・8.0.0・8.3.0・9.0.0・9.1.0のAARを取得し、javap で公開APIを書き出して版ごとに比べました。
| API | 7.1.1 | 8.3.0 | 9.1.0 |
|---|---|---|---|
enablePendingPurchases()(引数なし) |
非推奨 | 削除 | 削除 |
querySkuDetailsAsync |
非推奨 | 削除 | 削除 |
queryPurchaseHistoryAsync |
非推奨 | 削除 | 削除 |
queryPurchasesAsync(String, …) |
非推奨 | 削除 | 削除 |
SkuDetails・SkuDetailsParams |
非推奨 | 残る | 削除 |
BillingClient.SkuType |
非推奨 | 残る | 削除 |
QueryPurchaseHistoryParams |
あり | 残る | 削除 |
BillingFlowParams.Builder.setSkuDetails |
非推奨 | 残る | 削除 |
8.0.0で消えたのはSKU系の「メソッド」で、クラスそのものは8.3.0まで残っていました。9.0.0でクラスごと消えています。リリースノートだけを読んで「9.0.0は小さな変更」と判断すると、SKU系のクラスを型として使っている箇所(画面に渡すモデルやテストコード)で足をすくわれます。ProductDetailsResponseListener の引数が List<ProductDetails> から QueryProductDetailsResult に変わったのは8.0.0です。
7系の書き方で書いた次のコードを9.1.0に対してコンパイルすると、以下のエラーになります。出力は主要なエラー行だけを抜粋しています。
import android.content.Context
import com.android.billingclient.api.*
fun legacy(ctx: Context, l: PurchasesUpdatedListener) {
val client = BillingClient.newBuilder(ctx).setListener(l).enablePendingPurchases().build()
val params = SkuDetailsParams.newBuilder().setSkusList(listOf("coin_100")).setType(BillingClient.SkuType.INAPP).build()
client.querySkuDetailsAsync(params) { _, _ -> }
client.queryPurchaseHistoryAsync(BillingClient.ProductType.INAPP) { _, _ -> }
}
$ kotlinc Legacy.kt -cp billing-9.1.0/classes.jar:android-35/android.jar
Legacy.kt:5:63: error: no value passed for parameter 'p0'.
Legacy.kt:6:18: error: unresolved reference 'SkuDetailsParams'.
Legacy.kt:6:102: error: unresolved reference 'SkuType'.
Legacy.kt:7:12: error: unresolved reference 'querySkuDetailsAsync' on receiver of type 'BillingClient'.
Legacy.kt:8:12: error: unresolved reference 'queryPurchaseHistoryAsync' on receiver of type 'BillingClient'.
同じコードは7.1.1では非推奨の警告5件だけで通り、8.3.0では6行目(SkuDetailsParams と SkuType)を除く箇所がエラーになりました。移行の判断は次のとおりです。
- 版7から上げるなら、8を挟まず9.1.0へ直接上げる。移行ガイドは7から9への移行を前提に手順を書いており、8で止めても2027年8月31日に再び同じ作業が来る。
queryPurchaseHistoryAsyncで無料トライアルの対象者を判定していたなら、クライアントだけでは置き換えられない。対象判定はgetSubscriptionOfferDetails()が返すオファーに任せ、消費済みの購入履歴はサーバーで持つ設計に変える。ここを後回しにすると、トライアルの二重付与が起きる。- Unityなどのプラグイン経由でPBLを使っているなら、自分のコードを直す前にプラグインが内包する版を確認する。プラグインが旧APIに依存している場合は、PBLの依存バージョンだけを強制更新せず、対応済みプラグインへの更新かプラグイン自体の修正が必要になる。
ライセンステスターとPlay Billing Labでのテスト
課金のテストは、Play Consoleでテスト用のGoogleアカウントをライセンステスターに登録するところから始めます。公式のテストガイドによると、ライセンステスターならパッケージ名が一致していればデバッグ署名のビルドをサイドロードしても課金を試せます。ただし下書きや内部テストトラックのアプリには支出の上限があり、それを超えるテストにはクローズド以上のトラックへの公開が必要です。
テスト用の支払い手段と更新周期の短縮
ライセンステスターには「Test instrument, always approves」などのテスト用支払い手段が表示され、実際には課金されません。数分後に承認または拒否される遅延型の手段や、チャージバックを再現する手段もあり、保留中の購入と払い戻しの処理を試せます。定期購入は本番より速く更新され、更新は無料トライアルと導入期間を除いて最大6回です。
| 本番の期間 | テスト時の更新間隔 |
|---|---|
| 1週間 | 5分 |
| 1か月 | 5分 |
| 3か月 | 10分 |
| 6か月 | 15分 |
| 1年 | 30分 |
公式ガイドには未承認購入の払い戻しを3分後とする説明と、承認期間を5分とする表が併存しています。5分間の猶予を前提にせず、テスト購入も速やかに承認・消費してください。
Play Billing Labの国・オファー・状態遷移のテスト機能
Play Billing LabはGoogleがPlayストアで配布しているテスト用アプリです。Playの国の切り替え、同じアカウントで無料トライアルや導入価格を繰り返し試すこと、他の購読者に影響させずに価格変更を試すこと、更新・猶予期間・アカウント保留への遷移を早めることができます。課金に使うアカウントと同じアカウントでログインし、そのアカウントをライセンステスターに登録しておく必要があります。国・トライアル・実決済手段の設定は2時間で切れます。
9.1.0のAARのマニフェストには、Play Billing Labのパッケージ(com.google.android.apps.play.billingtestcompanion)に接続するための queries 宣言が入っています。ただし、Labの応答シミュレーター(Response Simulator)で応答コードを上書きするには、テスト用の AndroidManifest.xml に com.google.android.play.billingclient.enableBillingOverridesTesting を true にするメタデータを足す必要があります。公式の手順は、誤って本番に出さないよう NONPRODUCTION のメタデータも併記し、本番ビルドではどちらも外すよう求めています。
Google Playの手数料:日本は2026年9月30日から新体系
日本では2026年9月30日から手数料の体系が変わりました。Play Consoleヘルプの新手数料の説明によると、サービス手数料は課金方法を問わずかかり、Google Play Billingを使う取引には日本では5%の決済手数料(billing fee)が加わります。
| 取引(Google Play Billing利用) | 新規インストール | 既存インストール |
|---|---|---|
| 定期購入 | 10%+5% | 10%+5% |
| 一回限りの商品(標準) | 20%+5% | 25%+5% |
| 一回限りの商品(プログラム参加時) | 15%+5% | 20%+5% |
| 年間収益の最初の100万ドル分 | 10%+5% | 10%+5% |
「新規インストール」は、ユーザーがそのアプリをGoogle Playから初めてインストールした日、またはPlay以外から入れたアプリを初めてPlay経由で更新した日が、その地域の切り替え日以降である取引を指します。プログラム参加時の料率は、Apps ExperienceプログラムかGames Level Upプログラムに参加した場合です。切り替え日は米国・英国・EEAが2026年6月30日、日本とオーストラリアが9月30日、韓国が12月31日、それ以外の国が2027年9月30日で、切り替え前の国では従来どおり15%(年間100万ドルまで・定期購入)と30%の体系が続きます。
9.1.0で追加された getBillingChoiceInfoAsync などは、こうした決済方法の選択プログラムに参加するアプリのためのAPIです。日本の制度の背景はスマホ新法の施行で変わった手数料と企業の対策で扱っています。
PBLを直接使うか課金SDKを挟むかの判断
Androidだけで課金し、サーバー側の検証とRTDNの受け口を自社で持てるなら、PBLを直接使えば課金SDKの追加利用料を避けられ、版の更新にも自分で追従できます。ただし、検証サーバーの開発・運用費を含む総費用は別途比較が必要です。iOSとAndroidの両方で定期購入を売り、購読状態を1か所で見たいなら、RevenueCatのような課金SDKを挟む方が実装は短く済みます。その代わり、PBLの版はSDKの更新待ちになります。期限の前にSDKの対応予定を確かめ、間に合わないならSDKの乗り換えか直接実装への切り替えを決めてください。
避けたいのは、サーバーを持たずにクライアントだけで定期購入を完結させる構成です。解約や払い戻しをアプリが起動するまで検知できず、権利の剥奪が遅れます。設計から相談したい場合は、弊社のAndroidアプリ開発でも課金とサーバー検証を含めて対応しています。
よくある質問
Google Play Billing Libraryの最新バージョンは?
2026年10月13日時点の最新版は9.1.0で、2026年6月18日に公開されました。Googleのリポジトリでも9.1.0が最新です。新しい版が出ていないかは公式のリリースノートで確認してください。
Google Play Billing Libraryのサポート終了はいつ?
各版は2年で新規・更新に使えなくなります。版7は2026年8月31日(延長は11月1日まで)、版8は2027年8月31日、版9は2028年8月31日です。配信済みのアプリは期限後も動きますが、更新を出すには対応版への移行が必要です。
Play Billing Labとは何ですか?
Googleが配布する課金テスト用のAndroidアプリです。Playの国の切り替え、無料トライアルの繰り返しテスト、定期購入の状態遷移の短縮などができます。ライセンステスターに登録したアカウントで使います。2時間で失効するのは、Playの国、無料トライアル・導入価格、実決済手段のテスト設定です。
enableAutoServiceReconnectionとは?
8.0.0で追加された BillingClient.Builder のメソッドで、接続が切れた状態でAPIを呼んだときにライブラリが自動で接続し直します。有効にした場合は onBillingServiceDisconnected() で startConnection() を呼ばないでください。
com.android.billingclient:billingとbilling-ktxの違いは?
billing が本体で、billing-ktx は本体にKotlinのコルーチン用拡張関数を足したものです。版番号は両方とも同じで、9.1.0ならどちらも9.1.0です。Javaで書くなら本体だけで足ります。言語の選び方はAndroidアプリ開発の言語選定で整理しています。