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

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

對於使用受信任網路活動建立,並透過 Google Play 商店傳送的應用程式, 現在可以使用 Payment Request APIDigital Goods API 整合 Google Play 帳款服務這項功能適用於 Chrome 101 以上版本,且適用於 Android 和 ChromeOS。

本文將說明如何在 PWA 中新增 Google Play 帳款服務支援,並封裝 Google Play 帳款服務 在 ChromeOS 和 Play 商店的 Google Play 商店發行。

您將使用兩個網路平台 API,在 PWA 中加入 Play 帳款服務支援。 Digital Goods API (數位商品 API) 用於收集 SKU 資訊,以及檢查購買交易和授權 。您可以使用 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 支援 Digital Goods API,且 PWA 必須在 「信任的網路活動」,只要檢查 [ window 物件的 getDigitalGoodsService

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

數位商品 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 的建構函式會採用兩種參數:付款方式清單和 付款資料。

在「受信任的網路活動」中,您必須於 將 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 帳款服務會忽略這些值,並使用 值,因此可以填入虛構值:

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://flags 並搜尋 標記依據名稱:
    • #enable-debug-for-store-billing
  • 確認網站是透過 https 通訊協定代管。使用 http 會導致 API 為 undefined

使用 ChromeOS 裝置

ChromeOS 穩定版自 89 版起開始支援 Digital Goods API。在 同時,您可以測試 Digital Goods API:

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

邀請測試使用者和品質確保團隊參與

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

後續步驟

如本文件所述,Play Billing API 含有 Digital Goods API 和伺服器端元件