Digital Goods API と Payment Request API を使用して Google Play 請求サービス経由で支払いを受け取る

Google Play を通じて配信されているアプリで、デジタル商品の販売や定期購入の提供を行う場合は、Google Play 請求サービスを使用する必要があります。Google Play 請求サービスには、カタログ、料金、定期購入を管理するためのツール、便利なレポート、ユーザーにすでに馴染みのある Play ストアを利用した購入手続きフローがあります。

Trusted Web Activities を使用してビルドされ、Google Play ストアから配信されるアプリでは、Payment Request APIDigital Goods API を使用して Google Play Billing と統合できるようになりました。Android と ChromeOS の Chrome 101 以降で利用できます。

このガイドでは、PWA に Google Play Billing のサポートを追加し、ChromeOS と Google Play ストアの両方で Google Play ストアで配布できるようにパッケージ化する方法について説明します。

Play 請求サービスのサポートを PWA に追加するには、2 つのウェブ プラットフォーム API を使用します。Digital Goods API は、SKU 情報を収集し、Google Play ストアでの購入と利用資格を確認するために使用されます。Payment Request API は、Google Play ストアを支払い方法として設定し、購入フローを完了するために使用されます。

Google Play ストアでアプリを収益化する方法

アプリで Google Play ストアの Google Play 請求システムを使用して収益化を行う方法は 2 つあります。

  • アプリ内購入では、追加機能や広告の削除など、耐久性のある仮想アイテムと消費型の仮想アイテムの両方を販売できます。
  • 定期購入: ニュースの定期購入やメンバーシップなど、定期的な料金でコンテンツやサービスへの継続的なアクセス権をユーザーに提供します。

要件

Google Play 請求サービスを設定するには、以下が必要です。

Bubblewrap プロジェクトを更新する

Bubblewrap をインストールしていない場合は、インストールする必要があります。使用方法の詳細については、クイック スタートガイドをご覧ください。Bubblewrap がすでにある場合は、バージョン 1.8.2 以降にアップデートしてください。

Bubblewrap にもフラグが設定されています。これを有効にするには、プロジェクトのルートにある twa-manifest.json でプロジェクト構成を変更し、alphaDependenciesplayBilling 機能の両方を有効にする必要があります。

  ...,
  "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 Billing のお支払い方法を使用する必要があります。

async function makePurchase(service, sku) {
   // Define the preferred payment method and item ID
   const paymentMethods = [{
       supportedMethods: "https://play.google.com/billing",
       data: {
           sku: sku,
       }
   }];

   ...
}

支払いの詳細は必須ですが、Play 請求サービスではこれらの値が無視され、Google Play Console で SKU の作成時に設定された値が使用されるため、誤った値が入力される可能性があります。

const paymentDetails = {
    total: {
        label: `Total`,
        amount: {currency: `USD`, value: `0`}
    }
};

const request = new PaymentRequest(paymentMethods, paymentDetails);

支払いリクエスト オブジェクトで show() を呼び出して、支払いフローを開始します。Promise が成功した場合、お支払いが正常に完了した可能性があります。失敗した場合は、ユーザーが支払いを中止した可能性があります。

プロミスが成功した場合は、購入を確認して承認する必要があります。不正行為を防ぐため、このステップはバックエンドを使用して実装する必要があります。バックエンドに検証を実装する方法については、Play 請求サービスのドキュメントをご覧ください。購入を承認しない場合、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 によって管理されるクライアントサイド コンポーネントとサーバーサイド コンポーネントがあります。