如果 PWA 已在 Google Play 上架,且您想透過販售應用程式內商品或訂閱項目營利,就必須按照 Play 政策導入 Play 帳款服務。您需要在 PWA 中導入兩項 API:Digital Goods API 和 Payment Request API。
Digital Goods API
數位商品 API 是應用程式與 Google Play 之間的介面。您可以使用這項服務,擷取您在 Play 管理中心為應用程式內商品和訂閱項目輸入的數位產品和詳細資料,以及使用者現有的購買交易。如果您尚未在 Play 管理中心新增應用程式內商品或訂閱項目,請務必按照這篇文章的說明,在 Play 管理中心設定 Google Play 結帳服務。
2021 年 11 月 30 日發布的 ChromeOS 96 實作了 Digital Goods API 2.0。
第一版 Digital Goods API 的來源試用已於 2022 年 1 月 30 日結束。因此已淘汰,目前僅提供 API 第 2 版。
ChromeOS 103 已於 2022 年 6 月 23 日發布,並實作了 Digital Goods API 2.1。這個版本沒有任何破壞性變更,只包含新方法和額外欄位:listPurchaseHistory() 和 itemType。
註冊參加來源試用
注意:目前可透過原始碼試用機制使用 Digital Goods API。這項機制可讓開發人員搶先存取新的 Web API。您需要註冊 Digital Goods API v2 原始碼試用,並要求權杖,然後在來源中的任何頁面提供權杖。
註冊原始試用後,您會看到「有效期限」日期,這是保證權杖可運作的期限。請記得在該日期前續訂權杖,才能繼續參加試用。以原始碼試用形式提供的 API 可能會有異動,因此請務必隨時掌握您參與的原始碼試用計畫最新變更。如有任何問題,請參閱 Digital Goods API 說明文件。
Payment Request API
付款要求 API 會在購買時處理實際的付款交易。這項服務會使用 Digital Goods API 提供的項目詳細資料,透過適當的付款方式 (在本例中為 Google Play 結帳系統) 進行應用程式內購。
偵測 Digital Goods API 功能
如要確認是否已在網站上正確啟用 API,請透過原始碼試用檢查 window 物件中的 getDigitalGoodsService 方法。
if ('getDigitalGoodsService' in window) { // Digital Goods API is supported! } else { console.log('DigitalGoodsService is not available.'); // Use another payment method }
連線至 Google Play 帳款服務
Digital Goods API 的設計與各種瀏覽器和數位商店相容,類似於 Payment Request API 不受瀏覽器限制,且可搭配不同付款服務供應商使用。如要取得與 Google Play 帳單服務相關聯的服務例項,請將字串 "https://play.google.com/billing" 做為付款方式傳遞至 getDigitalGoodsService()。
如果該方法擲回錯誤,表示 Google Play 帳款服務付款方式無法使用 (例如使用者透過瀏覽器存取您的 PWA)。請改用其他付款方式進行交易。
if ('getDigitalGoodsService' in window) { // Digital Goods API is supported! try { const service = await window.getDigitalGoodsService('https://play.google.com/billing'); // Google Play Billing service is available } catch (error) { // Google Play Billing service is not available. Use another payment flow. } }
取得商品詳細資料
將 Digital Goods 服務連結至 Google Play 後,您就能使用 API 擷取產品和購買交易的相關資訊。
您可以使用 getDetails() 方法,取得在 Play 管理中心設定的項目相關資訊。應用程式 UI 應向使用者顯示產品名稱、說明和價格等資訊,讓他們瞭解可購買的產品和價格。
getDetails() 方法需要項目 ID 清單,這些 ID 對應您在 Play 管理中心建立的應用程式內商品和訂閱項目的產品 ID。
const itemDetails = await service.getDetails(['product_1', 'product_2', 'product_3']); for (const item of itemDetails) { // Display item information to user displayItem(item.title, item.description, item.price); }
如要取得使用者所在地區的適當價格,您需要進行一些額外的格式設定:
const localePrice = new Intl.NumberFormat(navigator.language, { style: 'currency', currency: item.price.currency, }).format(item.price.value);
注意:Digital Goods API 不提供取得項目 ID 清單的方法。您必須將這些值硬式編碼至用戶端,或從後端伺服器擷取這些值。不過,您可以使用 Google Play Developer API 從後端查詢項目 ID 清單。(如要進一步瞭解如何在後端伺服器中導入主要 Play 結帳元件,無論選擇哪種解決方案,請務必確保商品 ID 與 Play 管理中心中的 ID 一致。
在 API 2.1 版中,getDetails() 傳回的其中一個欄位是 itemType。這是列舉,值為 ”product” 或 ”subscription”,分別表示對應項目是應用程式內商品或訂閱項目。如果需要對每種產品類型套用不同的處理方式,區分這兩種產品類型就很有用。舉例來說,您可能有一個專供使用者訂閱的頁面,以及另一個用於其他非訂閱型產品的頁面。此外,您也可以藉此瞭解後端應使用哪個 Google Play Developer API REST 資源 (purchases.products 或 purchases.subscriptions)。
購買商品
向使用者顯示產品和詳細資料後,您可以使用 Payment Request API 建構購買流程。與 Digital Goods API 搭配使用時,只需要一個輸入參數:methodData。
Play 結帳系統一次只能購買一項商品,且 Play 伺服器已知道商品價格和詳細資料,因此不需要 details 參數。詳情請參閱說明。
在 PaymentRequest 中使用 methodData 參數的 supportedMethods 成員,以字串 "https://play.google.com/billing" 將 Google Play 帳款服務識別為付款方式。然後在 data 成員中,將商品 ID 做為 sku 傳遞。
const paymentMethodData = [ { supportedMethods: 'https://play.google.com/billing', data: { sku: item.itemId, }, }, ];
接著建立付款要求,並呼叫 show() 來啟動付款流程:
const request = new PaymentRequest(paymentMethodData); const paymentResponse = await request.show();
系統會向使用者顯示 Play 購買使用者介面,其中包含使用者嘗試購買的產品詳細資料。他們可以放棄交易或繼續付款。如果使用者取消付款,show() 傳回的 Promise 會因錯誤而遭拒。如果使用者順利付款並完成購買交易,系統會使用 PaymentResponse 解決 promise。付款回應的 details 屬性會傳回購買交易權杖。
為防範詐欺行為,請務必在後端伺服器上驗證購買交易和購買憑證。此外,建議您追蹤使用者及其相關聯的購買交易權杖。瞭解如何在後端伺服器上實作驗證。
驗證購買交易後,請在付款回應中呼叫 complete(),完成付款流程並關閉結帳 UI。您也可以傳遞選用的 result 字串,指出付款程序的狀態。瀏覽器會自行決定是否向使用者顯示這項結果。Chrome 不會建立任何使用者可見的提示,因此建議您在 PWA 中顯示自己的錯誤或成功訊息。
/* Changes were recently made so that the PaymentResponse `details` property returns the purchase token as `purchaseToken` instead of `token`. Note that `token` will be deprecated at some point in the future. To ensure that your app won't be affected by this, make the change to `purchaseToken` in your client code and use the latest version of Bubblewrap (v1.13.5 and later) to update and generate a new app package to upload to the Play Console. */ const { purchaseToken } = paymentResponse.details; let paymentComplete; if (validatePurchaseOnBackend(purchaseToken)) { paymentComplete = await paymentResponse.complete('success'); // Let user know their purchase transaction has successfully completed and been verified } else { paymentComplete = await paymentResponse.complete('fail'); // Let user know their purchase transaction failed to verify }
升級和降級訂閱方案
應用程式內商品和訂閱項目的購買流程相同。不過,Google Play 提供升級和降級等額外訂閱項目購買選項,建構付款方式的 data 時,您需要傳入下列項目,才能啟動升級或降級流程:
sku:這是要升級或降級的新訂閱項目 ID。oldSku:這是使用者目前訂閱方案的項目 ID。purchaseToken:這是使用者目前訂閱項目的購買交易權杖。如先前所述,建議您在後端追蹤購買交易權杖。在這種情況和其他情況下,您也應該將使用者與目前的購買項目和購買交易權杖建立關聯。prorationMode:新訂閱方案取代使用者目前的訂閱方案後,系統會依此方式收費。
| 依比例計費模式 | 說明 |
|---|---|
immediateAndChargeProratedPrice |
系統會立即升級訂閱項目,並保持相同的帳單週期,接著,系統會向使用者收取剩餘訂閱期的費用差額。 |
immediateAndChargeFullPrice |
系統將訂閱項目升級或降級,並立即向使用者收取新授權的全額費用。系統會將先前訂閱項目的剩餘價值,依比例計算時間,轉用於新的訂閱方案。Google Play 帳款服務程式庫 4.0 版最近新增了這個按比例計算模式。現在只要使用 1.13.5 以上版本的 Bubblewrap,即可使用這項功能。 |
immediateWithoutProration |
暫時停用:如果使用這種按比例計算模式,使用者可能會在一個帳單週期內升級訂閱方案,但不必支付額外費用,因此可能出現詐欺行為。請注意,我們正在修正問題,因此暫時停用了這項模式。 |
immediateWithTimeProration |
訂閱項目會立即升級或降級。根據費用差額調整任何剩餘時間,並將下一個帳單日期往後推延,計入新的訂閱項目。這是預設行為。 |
deferred |
只有在續訂時,系統才會升級或降級訂閱項目。這項功能特別適合用於降級。 |
unknownSubscriptionUpgradeDowngradePolicy |
未設定政策。我們不建議這麼做。 |
如要進一步瞭解 Google Play Billing Library 的不同按比例計算模式,請參閱參考說明文件。如要進一步瞭解訂閱升級和降級,以及按比例分配模式建議,請參閱 Android 開發人員說明文件。
這些額外欄位的使用方式如下:
const paymentMethod = [ { supportedMethods: 'https://play.google.com/billing', data: { sku: item.itemId, oldSku: oldPurchase.itemId, purchaseToken: oldPurchase.purchaseToken, prorationMode: 'immediateAndChargeProratedPrice', }, }, ];
其中 item 是使用者嘗試升級或降級的新訂閱方案的 ItemDetails,而 oldPurchase 是使用者目前訂閱方案的 PurchaseDetails。
確認購買交易
使用者購買商品後,您應授予適當的權利 (存取剛購買的商品或內容)。然後確認購買交易。確認購買交易後,Google Play 就會知道您已收到並妥善處理該筆交易。
注意:如果未在購買後 72 小時內確認交易,系統會將款項退還給使用者,並撤銷購買交易。購買交易權杖將失效,因此查詢現有購買交易時,系統不會傳回已撤銷的購買交易。這樣一來,如果發生網路錯誤,導致使用者無法取得商品權利,就不會遭到不當收費。
您應使用 Google Play Developer API,從後端伺服器確認購買交易。建議您在後端伺服器中一併授予權利並確認購買交易。
- 使用者在用戶端完成購買後,請在要求中將購買權杖和商品 ID 傳送至後端伺服器。
- 在後端,如要取得購買交易的詳細資料以進行驗證,請呼叫:
- 應用程式內商品:purchases.products.get。
- 訂閱項目:purchases.subscriptions.get。
- 在後端資料庫中授予適當的授權。
- 接著呼叫下列項目來確認購買交易:
- 應用程式內商品的 purchases.products.acknowledge。
- 訂閱項目:purchases.subscriptions.acknowledge。
消耗購買的產品
確認購買交易後,Google Play 就會知道使用者已擁有該商品,不應允許再次購買。如果使用者只需要購買一次,就能永久擁有該商品 (例如遊戲角色造型),則該商品為非消耗性商品。
或者,您可能限制使用者一次只能擁有一個項目。使用者必須先使用該項目,才能再次購買。使用者「使用」商品時,您應呼叫 consume() 方法,通知 Google Play 使用者已消耗商品。Google Play 隨後會讓使用者再次購買該商品。
如果使用者可擁有複數個項目,則必須能夠重複購買,不必先使用 (我們稱這類項目為可重複項目)。同樣地,使用者必須「消耗」這些商品,Google Play 才會允許他們再次購買。因此,即使使用者尚未使用商品,您仍須呼叫 consume() 方法,將商品標示為已消耗。
// After the user purchases the item, send the purchase token and item ID to your backend to grant the entitlement and acknowledge it right away . . . // When the user uses the item or if it is a repeatable item, consume it so it’s available for purchase again. service.consume(purchaseToken); }
查看現有購買交易
最後一個重要使用者流程是檢查現有購買交易 (尚未使用的應用程式內商品和持續訂閱項目),讓使用者瞭解目前擁有的訂閱項目或商品。這些現有購買交易是透過任何裝置在應用程式內或 Play 商店進行的 Google Play 購買交易。在 Play 商店中從應用程式外部進行的購買交易稱為「應用程式外購買交易」。
擷取現有購買交易時,您也應檢查確認狀態,並確認先前進行但未正確確認的任何購買交易。建議您盡快確認購買交易,確保使用者的權利為最新狀態,並正確反映在應用程式中。
Digital Goods API listPurchases() 方法會傳回 PurchaseDetails 清單,其中包含每筆交易的 itemId 和 purchaseToken。您需要在後端伺服器上使用 Google Play Developer API,檢查購買交易的狀態並適當確認。請採取以下措施:
- 在用戶端呼叫 Digital Goods API
listPurchases()方法,擷取使用者的購買項目清單。 - 每次購買時,請將
purchaseToken和itemId傳遞至後端。 - 視情況在後端資料庫中授予權利。
- 然後呼叫:並檢查
acknowledgementState。- 應用程式內商品:purchases.products.get。
- 訂閱項目:purchases.subscriptions.get。
- 如果值為 0 (尚未確認),請呼叫:
- 應用程式內商品的 purchases.products.acknowledge。
- 訂閱項目:purchases.subscriptions.acknowledge。
進一步瞭解如何在授權前,先在後端伺服器上驗證購買交易。
購買記錄
listPurchases 會傳回使用者現有購買交易的相關資訊,而 listPurchaseHistory() 方法 (適用於 API 2.1 版) 則會傳回使用者針對各個項目最近一次的購買交易,即使購買交易已過期、取消或消耗亦是如此。listPurchaseHistory() 方法會傳回 PurchaseDetails 清單,其中包含每筆交易的 itemId 和 purchaseToken,您需要在後端伺服器上使用 Google Play Developer API 擷取更多資訊。
應用程式外購
應用程式外購是指並非透過一般應用程式內購流程進行的購買交易。這類交易通常會在 Play 商店進行,而非在應用程式內。使用者可透過兩種主要方式在應用程式外進行交易:
- 兌換促銷代碼:在 Play 商店使用者選單中,依序前往「優惠與通知」->「兌換促銷代碼」或「付款與訂閱」->「使用兌換代碼」。
- 重新訂閱:在 Play 商店使用者選單中,依序前往「付款與訂閱」->「訂閱項目」。使用者可以在這裡管理不同應用程式的所有訂閱項目。如果訂閱方案已到期或取消,使用者可以選擇「重新訂閱」。
使用者透過 Play 商店重新訂閱時,系統不會自動確認購買交易,因此可能會退款給使用者。這是刻意設計的行為,因為使用者只有在開啟應用程式時,才會因訂閱而產生費用。使用者可能會看到「確認訂閱」訊息,提醒他們開啟應用程式。
開發人員必須在使用者啟動應用程式時,實作這些確認作業。因此,我們建議您檢查現有購買交易 (通常是在應用程式首次啟動時),並確認任何尚未確認的購買交易。
允許使用者管理訂閱項目
為提供良好的使用者體驗,請務必讓使用者在應用程式中管理及取消訂閱。建議您在設定頁面或選單中建立深層連結,將使用者重新導向至 Play 商店的應用程式訂閱管理頁面。請將下列網址替換為適當的「sub-product-id」和「app-package-name」:
https://play.google.com/store/account/subscriptions?sku=sub-product-id&package=app-package-name後續步驟
這些使用者流程和程式碼片段是基本實作方式,可說明如何在 PWA 中使用 Digital Goods API 和 Payment Request API 實作 Play Billing。您應根據應用程式的情境和用途,適當使用 API。如需端對端導入範例,請參閱我們的開放原始碼範例。
接著,請參閱這篇文章,瞭解如何在後端伺服器中導入重要的 Play 結帳服務元件,確保應用程式安全無虞,並隨時更新使用者的權利。