運用 Digital Goods API 和 Payment Request API 透過 Google Play 帳款服務接收付款

安德烈西普里亞尼班達拉
André Cipriani Bandarra

如果您的應用程式是透過 Google Play 發行,而且您想販售數位商品或提供訂閱項目,則必須使用 Google Play 帳款服務。Google Play 帳款服務提供多項工具,可讓您管理目錄、價格和訂閱項目、實用報表,以及由使用者熟悉的 Play 商店提供的結帳流程。

如果應用程式是透過Trusted Web Activities 建構,並透過 Google Play 商店提供,您現在可以使用 Payment Request APIDigital Goods API 來整合 Google Play 帳款服務。這項功能適用於 Android 和 ChromeOS 適用的 Chrome 101 以上版本。

本指南將說明如何為 PWA 新增 Google Play 帳款服務支援功能,然後封裝 SDK,以便透過 ChromeOS 和 Play 商店在 Google Play 商店發行。

您將使用兩個網路平台 API,為您的 PWA 新增 Play 帳款服務支援。Digital Goods API 可用來收集 SKU 資訊,以及檢查 Play 商店中的購買交易和授權。Payment Request API 可用於將 Google Play 商店設為付款方式並完成購買流程。

如何在 Play 商店中透過應用程式營利

讓應用程式在 Play 商店中透過 Google Play 帳款服務營利的方式有兩種:

  • 應用程式內購允許銷售耐用性和消耗性虛擬商品,例如其他功能,或移除廣告。
  • 訂閱:可讓使用者定期付費存取內容或服務,例如新聞訂閱或會員方案。

需求條件

如要設定 Google Play 帳款服務,您需要:

更新 Bubblewrap 專案

如果尚未安裝對話框,請先進行安裝。如要進一步瞭解如何開始使用,請參閱快速入門指南。如果已安裝對話框,請務必更新至 1.8.2 以上版本。

Bubblewrap 也擁有旗幟後方的功能。如要啟用這項功能,您必須修改位於專案根目錄的 twa-manifest.json 中的專案設定,並啟用 alphaDependenciesplayBilling 功能:

  ...,
  "enableNotifications": true,
  "features": {
    "playBilling": {
      "enabled": true
    }
  },
  "alphaDependencies": {
    "enabled": true
  },
  ...

更新設定檔後,請執行 bubblewrap update 以將設定套用至專案,其後執行 bubblewrap build 來產生新的 Android 套件,並將此套件上傳至 Play 商店。

偵測 Digital Goods API 和 Google Play 帳款服務可用性的功能

目前只有 Chrome 支援 Digital Goods API,前提是該 PWA 是在受信任的網路活動中執行,而且只要檢查 window 物件上的 getDigitalGoodsService,即可偵測是否可用:

if ('getDigitalGoodsService' in window) {
 // Digital Goods API is supported!
}

Digital Goods API 適用於任何瀏覽器,且支援不同的商店。如要檢查是否支援特定商店後端,您必須叫用 getDigitalGoodsService() 並將商店 ID 做為參數傳遞。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 的建構函式有兩個參數:付款方式清單和付款詳情清單。

在受信任的網路活動中,您必須使用 Google Play 帳款服務付款方式,將 https://play.google.com/billing 設為 ID,然後將產品 SKU 新增為資料成員:

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 帳款服務會忽略這些值,並使用在 Play 管理中心建立 SKU 時設定的值,因此能填入假值:

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

const request = new PaymentRequest(paymentMethods, paymentDetails);

呼叫付款要求物件的 show(),啟動付款流程。如果 Promise 成功 那麼就可以付款成功如果無法付款,使用者可能取消付款。

如果 promise 成功,您就必須驗證並確認購買交易。 為防範詐欺行為,這個步驟必須使用後端實作。請參閱 Play 帳款服務說明文件,瞭解如何在後端實作驗證。如果您未確認購買交易,使用者會在三天後收到退款,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://flags 並依名稱搜尋標記,即可在 Chrome 中啟用下列標記:
    • #enable-debug-for-store-billing
  • 確認網站是由 HTTPS 通訊協定代管。使用 HTTP 會導致 API 為 undefined

使用 ChromeOS 裝置

自 89 版起,ChromeOS 穩定版將提供 Digital Goods API。在此期間,您可以測試 Digital Goods API:

  • 請在裝置上透過 Play 商店安裝應用程式。
  • 確認網站是由 HTTPS 通訊協定代管。使用 HTTP 會導致 API 為 undefined

加入測試使用者和品質確保團隊

Play 商店提供測試功能,包括使用者測試帳戶和測試 SKU。詳情請參閱 Google Play 帳款服務測試說明文件

接下來該怎麼做?

如本文件所述,Play Billing API 具有由 Digital Goods API 管理的用戶端元件和伺服器端元件。