アプリを Google Play で配信し、デジタル商品を販売または定期購入を提供する場合は、Google Play 請求サービスを使用する必要があります。Google Play 請求サービスには、カタログ、料金、定期購入を管理するためのツール、便利なレポート、ユーザーにすでに馴染みのある Play ストアによる購入手続きフローがあります。
Trusted Web Activities を使用してビルドされ、Google Play ストアから配信されるアプリでは、Payment Request API と Digital Goods API を使用して Google Play 請求システムと統合できるようになりました。Android と ChromeOS では Chrome 101 以降で利用できます。
このガイドでは、PWA に Google Play Billing のサポートを追加し、ChromeOS と Google Play ストアの両方で Google Play ストアで配信できるようにパッケージ化する方法について説明します。
2 つのウェブ プラットフォーム API を使用して、PWA に Play 請求サービスのサポートを追加します。Digital Goods API は、SKU 情報を収集し、Google Play ストアでの購入と利用資格を確認するために使用されます。Payment Request API は、Google Play ストアを支払い方法として設定し、購入フローを完了するために使用されます。
Google Play ストアでアプリを収益化する方法
アプリで Google Play ストアの Google Play 請求システムを使用して収益化を行う方法は 2 つあります。
- アプリ内購入では、追加機能や広告の削除など、耐久性のある仮想アイテムと消費型の仮想アイテムの両方を販売できます。
- 定期購入: ニュースの定期購入やメンバーシップなど、定期的な料金でコンテンツやサービスへの継続的なアクセス権をユーザーに提供します。
要件
Google Play 請求サービスを設定するには、以下が必要です。
- Google Play デベロッパー アカウントと Google お支払い販売者アカウントが相互にリンクされていること。
- 公開テストトラック、クローズド テストトラック、内部テストトラックにリリースされているGoogle Play ストアの掲載情報。
- Google Play ストアでアプリのアイテムと定期購入を作成して構成する。
- Digital Asset Links の構成が機能している Bubblewrap で生成されたプロジェクト。
Bubblewrap プロジェクトを更新する
Bubblewrap をインストールしていない場合は、インストールする必要があります。利用を開始する方法については、クイック スタートガイドをご覧ください。Bubblewrap がすでにある場合は、バージョン 1.8.2 以降にアップデートしてください。
Bubblewrap にも、フラグで制御される機能があります。これを有効にするには、プロジェクトのルートにある twa-manifest.json
でプロジェクト構成を変更し、alphaDependencies
と playBilling
機能の両方を有効にする必要があります。
...,
"enableNotifications": true,
"features": {
"playBilling": {
"enabled": true
}
},
"alphaDependencies": {
"enabled": true
},
...
構成ファイルを更新したら、bubblewrap update
を実行して構成をプロジェクトに適用し、続いて bubblewrap build
を実行して新しい Android パッケージを生成して、このパッケージを Google Play ストアにアップロードします。
Digital Goods API と Google Play 請求サービスの利用状況を検出する機能
現在、Digital Goods API は、PWA が信頼できるウェブ アクティビティ内で実行されている場合にのみ Chrome でサポートされています。この API が使用可能かどうかは、window
オブジェクトで getDigitalGoodsService
を確認することで検出できます。
if ('getDigitalGoodsService' in window) {
// Digital Goods API is supported!
}
Digital Goods API はどのブラウザでも使用でき、さまざまなストアをサポートしています。特定のストア バックエンドがサポートされているかどうかを確認するには、ストア ID をパラメータとして渡して getDigitalGoodsService()
を呼び出す必要があります。Google Play ストアは文字列 https://play.google.com/billing
で識別されます。
if ('getDigitalGoodsService' in window) {
// Digital Goods API is supported!
try {
const service =
await window.getDigitalGoodsService('https://play.google.com/billing');
// Google Play Billing is supported!
} catch (error) {
// Google Play Billing is not available. Use another payment flow.
return;
}
}
SKU の詳細を取得する
Digital Goods API は getDetails()
を提供します。これにより、支払いバックエンドから商品のタイトル、説明、最も重要な価格などの情報を取得できます。
この情報をユーザー インターフェースで使用し、ユーザーに詳細情報を提供できます。
const skuDetails = await service.getDetails(['shiny_sword', 'gem']);
for (item of skuDetails) {
// Format the price according to the user locale.
const localizedPrice = new Intl.NumberFormat(
navigator.language,
{style: 'currency', currency: item.price.currency}
).format(item.price.value);
// Render the price to the UI.
renderProductDetails(
item.itemId, item.title, localizedPrice, item.description);
}
購入フローを構築する
PaymentRequest のコンストラクタは、支払い方法のリストと支払いの詳細のリストという 2 つのパラメータを取ります。
信頼できるウェブ アクティビティ内では、https://play.google.com/billing
を ID として設定し、商品の SKU をデータメンバーとして追加することで、Google Play 請求サービスのお支払い方法を使用する必要があります。
async function makePurchase(service, sku) {
// Define the preferred payment method and item ID
const paymentMethods = [{
supportedMethods: "https://play.google.com/billing",
data: {
sku: sku,
}
}];
...
}
支払い情報は必須ですが、Google Play Billing ではこれらの値は無視され、Google Play Console で SKU を作成するときに設定された値が使用されるため、偽の値を入力できます。
const paymentDetails = {
total: {
label: `Total`,
amount: {currency: `USD`, value: `0`}
}
};
const request = new PaymentRequest(paymentMethods, paymentDetails);
支払いリクエスト オブジェクトで show()
を呼び出して、支払いフローを開始します。Promise が成功した場合、お支払いが正常に完了した可能性があります。失敗した場合は、ユーザーが支払いを中止した可能性があります。
プロミスが成功した場合は、購入を確認して承認する必要があります。不正行為を防ぐため、このステップはバックエンドを使用して実装する必要があります。Google Play Billing のドキュメントで、バックエンドに確認を実装する方法をご覧ください。購入を承認しない場合、3 日後にユーザーに払い戻しが行われ、Google Play は購入を取り消します。
...
const request = new PaymentRequest(paymentMethods, paymentDetails);
try {
const paymentResponse = await request.show();
const {purchaseToken} = paymentResponse.details;
// Call backend to validate and acknowledge the purchase.
if (await acknowledgePurchaseOnBackend(purchaseToken, sku)) {
// Optional: tell the PaymentRequest API the validation was
// successful. The user-agent may show a "payment successful"
// message to the user.
const paymentComplete = await paymentResponse.complete('success');
} else {
// Optional: tell the PaymentRequest API the validation failed. The
// user agent may show a message to the user.
const paymentComplete = await paymentResponse.complete('fail');
}
} catch(e) {
// The purchase failed, and we can handle the failure here. AbortError
// usually means a user cancellation
}
...
必要に応じて、purchaseToken で consume()
を呼び出して、購入を使い果たしたとしてマークし、再購入できるようにします。
以上をまとめると、購入方法は次のようになります。
async function makePurchase(service, sku) {
// Define the preferred payment method and item ID
const paymentMethods = [{
supportedMethods: "https://play.google.com/billing",
data: {
sku: sku,
}
}];
// The "total" member of the paymentDetails is required by the Payment
// Request API, but is not used when using Google Play Billing. We can
// set it up with bogus details.
const paymentDetails = {
total: {
label: `Total`,
amount: {currency: `USD`, value: `0`}
}
};
const request = new PaymentRequest(paymentMethods, paymentDetails);
try {
const paymentResponse = await request.show();
const {purchaseToken} = paymentResponse.details;
// Call backend to validate and acknowledge the purchase.
if (await acknowledgePurchaseOnBackend(purchaseToken, sku)) {
// Optional: consume the purchase, allowing the user to purchase
// the same item again.
service.consume(purchaseToken);
// Optional: tell the PaymentRequest API the validation was
// successful. The user-agent may show a "payment successful"
// message to the user.
const paymentComplete =
await paymentResponse.complete('success');
} else {
// Optional: tell the PaymentRequest API the validation failed.
// The user agent may show a message to the user.
const paymentComplete = await paymentResponse.complete('fail');
}
} catch(e) {
// The purchase failed, and we can handle the failure here.
// AbortError usually means a user cancellation
}
}
既存の購入のステータスを確認する
Digital Goods API を使用すると、ユーザーが以前に購入したコンテンツ(別のデバイス、以前のインストール、プロモーション コードからの利用、アプリの最終的な起動時など)で、既存の利用資格(まだ使用されていないアプリ内購入や定期購入)があるかどうかを確認できます。
const service =
await window.getDigitalGoodsService('https://play.google.com/billing');
...
const existingPurchases = await service.listPurchases();
for (const p of existingPurchases) {
// Update the UI with items the user is already entitled to.
console.log(`Users has entitlement for ${p.itemId}`);
}
この機会に、以前に行われたが承認されていない購入を確認することもできます。ユーザーの利用資格がアプリに適切に反映されるように、できるだけ早く購入を承認することをおすすめします。
const service =
await window.getDigitalGoodsService("https://play.google.com/billing");
...
const existingPurchases = await service.listPurchases();
for (const p of existingPurchases) {
await verifyOrAcknowledgePurchaseOnBackend(p.purchaseToken, p.itemId);
// Update the UI with items the user is already entitled to.
console.log(`Users has entitlement for ${p.itemId}`);
}
統合をテストする
開発用 Android デバイスの場合
テスト用に、開発用 Android デバイスで Digital Goods API を有効にできます。
- 開発者モードが有効になっている Android 9 以降を使用していることを確認します。
- Chrome 101 以降をインストールします。
- Chrome で
chrome://flags
に移動し、フラグの名前で検索して、次のフラグを有効にします。#enable-debug-for-store-billing
- サイトが https プロトコルを使用してホストされていることを確認します。http を使用すると、API は
undefined
になります。
ChromeOS デバイスの場合
Digital Goods API は、ChromeOS 安定版のバージョン 89 以降で利用可能になります。一方、Digital Goods API はテストできます。
- Google Play ストアからデバイスにアプリをインストールします。
- サイトが https プロトコルを使用してホストされていることを確認します。http を使用すると、API は
undefined
になります。
テストユーザーと QA チーム
Google Play ストアには、ユーザー テスト アカウントやテスト SKU など、テスト用のアフォーダンスが用意されています。詳しくは、Google Play 請求サービスのテストに関するドキュメントをご覧ください。
次はどこに行く?
このドキュメントで説明されているように、Play Billing API には、Digital Goods API によって管理されるクライアントサイド コンポーネントとサーバーサイド コンポーネントがあります。
- Peter Conn のサンプル(https://github.com/PEConn/beer)をご覧ください。
- 購入の確認に関する Google Play のドキュメントをご覧ください。
- Google Play Developer API クライアント ライブラリのいずれかを使用することを検討してください。これらのライブラリは複数の言語で利用できます。
- アプリに定期購入モデルを実装する場合は、Google Play Billing の定期購入に関するドキュメントをご覧ください。
- リアルタイム デベロッパー通知(RTDN)を実装して通知をサブスクライブし、Google Play でステータスをポーリングするのではなく、定期購入のステータスが変更されたときにバックエンドに通知されるようにします。
linkedPurchaseToken
を実装して、重複する定期購入を防ぎます。正しく実装する方法については、こちらのブログ投稿をご覧ください。