運用 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 帳款服務。這項功能適用於 Chrome 101 以上版本,且適用於 Android 和 ChromeOS。

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

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

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

應用程式可透過下列兩種方式在 Play 商店中使用 Google 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 管理的用戶端元件,以及伺服器端元件。