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

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

如果應用程式是使用可信任的網頁活動建構,並透過 Google Play 商店提供,您現在可以使用Payment Request APIDigital Goods API 與 Google Play 結帳系統整合。適用於 Android 和 ChromeOS 的 Chrome 101 以上版本。

本指南將說明如何在 PWA 中加入 Google Play 帳款服務支援功能,並將其封裝為可在 ChromeOS 和 Play 商店中發布的應用程式。

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

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

應用程式可以透過 Google Play 帳單系統在 Play 商店營利,方法如下:

  • 應用程式內購可用於銷售永久性和消耗性虛擬商品,例如額外功能或移除廣告。
  • 訂閱項目:使用者可透過定期付費,持續存取內容或服務,例如新聞訂閱或會員資格。

需求條件

如要設定 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 套件,並將此套件上傳至 Play 商店。

偵測 Digital Goods API 和 Google Play 結帳系統可用性的功能

Chrome 目前僅在 PWA 在可信任的網路活動中執行時支援 Digital Goods API,您可以檢查 window 物件上的 getDigitalGoodsService,藉此偵測是否可使用此 API:

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 成功,表示付款可能已成功。如果失敗,使用者可能已中止付款。

如果承諾成功,您必須驗證並確認購買交易。為了防範詐欺行為,您必須使用後端實作這個步驟。請參閱 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 裝置上

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

  • 從裝置上的 Play 商店安裝應用程式。
  • 請確認網站是使用 https 通訊協定代管。使用 http 會導致 API undefined

與測試使用者和品質保證團隊合作

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

接下來要去哪裡?

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