提醒:自 2021 年 11 月 1 日起,現有應用程式的所有更新都必須採用帳款服務程式庫 3.0 以上版本。瞭解詳情

銷售訂閱項目

本主題說明如何處理訂閱的生命週期事件,例如續訂和到期日。本主題同時也說明了訂閱服務的其他功能,例如提供促銷活動以及允許使用者自行管理訂閱項目。

閱讀本主題前,請確認您已閲讀將 Google Play 帳款服務程式庫整合至應用程式一文,瞭解關於如何在應用程式中販售和管理產品的一般操作說明。

如果您尚未為應用程式設定訂閱產品,請參閱建立並設定產品

處理訂閱的生命週期

一個訂閱項目會在其生命週期中經歷各種狀態變更,而您的應用程式必須對每一項變更作出回應。若要檢查訂閱者的狀態,可以使用 Google Play 帳款服務程式庫中的 BillingClient.queryPurchasesAsync(),或 Google Play Developer API 中的 Purchases.subscriptions:get

BillingClient.queryPurchasesAsync() Purchases.subscriptions:get
狀態 是否傳回? isAutoRenewing 是否傳回? expiryTimeMillis paymentState autoRenewing
進行中 未來 1(已收到款項)
已取消 未來 1(已收到款項)
在寬限期內 未來 0(待付款)
保留中 不適用 過去 0(待付款)
已暫停 不適用 過去 1(已收到款項)
已過期 不適用 過去 不適用

如果應用程式將訂閱狀態儲存在安全的後端伺服器上,則應使用即時開發人員通知監聽狀態變更,以確保狀態保持同步。系統會針對影響訂閱狀態的事件(例如續訂和取消訂閲)傳送 SubscriptionNotification

應用程式必須處理下列各節所述的狀態變更。

新增訂閱項目

請務必遵循我們的建議處理新的購買交易。購買一項訂閱項目後,BillingClient.queryPurchasesAsync()SubscriptionNotification 會傳回該訂閱項目,並傳送類型為 SUBSCRIPTION_PURCHASED 的通知。收到這則通知時,需查詢 Google Play Developer API 來取得最新的訂閱狀態。訂閱資源類似如下所示:

{
  "kind": "androidpublisher#subscriptionPurchase",
  ...
  "expiryTimeMillis": next_renewal_date,
  "autoRenewing": true,
  ...
  "paymentState": 1  # Payment received
}

續訂

如果訂閱項目成功續訂,BillingClient.queryPurchasesAsync() 會持續傳回該訂閲項目。

續訂訂閲項目時,也會傳送 SUBSCRIPTION_RENEWED 通知。應用程式應確保使用者仍有權訂閱,並以 Google Play Developer API 傳回的訂閱資源中的新 expiryTimeMillis 來更新訂閱狀態。訂閱資源類似如下:

{
  "kind": "androidpublisher#subscriptionPurchase",
  ...
  "expiryTimeMillis": updated_expiration_time,
  "autoRenewing": true,
  ...
  "paymentState": 1  # Payment received
}

到期日

訂閱到期後,BillingClient.queryPurchasesAsync() 中不會再傳回訂閲項目,使用者將無法再存取該訂閱項目。

訂閱到期時,系統也會傳送類型為 SUBSCRIPTION_EXPIREDSubscriptionNotification。收到這則通知時,您應查詢 Google Play Developer API 來取得最新的訂閱狀態。訂閱資源類似如下所示:

{
  "kind": "androidpublisher#subscriptionPurchase",
  ...
  "expiryTimeMillis": expiry_time_in_past,
  "autoRenewing": false,
  ...
}

取消

使用者可以自發性地從 Play 商店取消訂閱項目,或者如果在處於帳戶保留狀態後他們沒有復原,則系統會自動取消訂閱項目。使用者取消訂閱項目後,在目前的帳單週期結束前仍可存取訂閲內容。帳單週期結束後,系統會撤銷存取權。

如果訂閱項目已取消,但訂閲項目尚未到期BillingClient.queryPurchasesAsync() 會傳回該訂閱項目。取消訂閱項目會觸發 SUBSCRIPTION_CANCELED 通知。收到這則通知時,從 Google Play Developer API 傳回的訂閱資源含有 autoRenewing = false,而 expiryTimeMillis 則含有使用者無法再存取該訂閱項目的日期。如果 expiryTimeMillis 是過去的日期,使用者會立即失去授權。否則,使用者應保留授權,直到授權到期為止。訂閱資源類似如下所示:

{
  "kind": "androidpublisher#subscriptionPurchase",
  ...
  "expiryTimeMillis": expiry_time,
  "autoRenewing": false,
  ...
  "paymentState": 1  # Payment received
  "cancelReason": integer # Reason the subscription was cancelled: user, billing issue, etc.
}

應用程式可以查看 Google Play Developer API 傳回的訂閱資源中的 cancelReason,瞭解取消訂閱項目的原因(例如客戶取消或出現帳單問題)。如果使用者取消了訂閱項目,您可以查看 cancelSurveyResult 欄位,瞭解使用者取消該訂閲項目的原因。

可以考慮在應用程式中顯示訊息,通知使用者訂閱項目已取消,例如「您的訂閱項目將於 date 到期」。應用程式也可以利用深層連結至 Google Play 商店,讓使用者還原訂閱項目

如果顯示這則訊息,您也應該讓使用者可以永久關閉這則訊息。

另請注意,取消的訊息可能會讓使用者感到困擾,特別是在使用者透過手動取消訂閲項目,而不是因為付款逾時而必須取消訂閱項目時。您可以選擇不通知手動取消訂閲項目的使用者。

撤銷

使用者可能因爲各種不同的原因訂閱項目遭到撤銷,例如應用程式使用 Purchases.subscriptions:revoke 撤銷訂閲項目或是拒付該筆購買交易。在這種情況下,應用程式應立即撤銷使用者的授權。BillingClient.queryPurchasesAsync() 不會再傳回撤銷的訂閱項目。發生這樣的情況時,系統也會傳送類型為 SUBSCRIPTION_REVOKEDSubscriptionNotification。收到這則通知時,從 Google Play Developer API 傳回的訂閱資源含有 autoRenewing = false,而 expiryTimeMillis 則含有使用者無法再存取該訂閱項目的日期。訂閱資源看起來類似如下:

{
  "kind": "androidpublisher#subscriptionPurchase",
  ...
  "expiryTimeMillis": expiry_time_in_past,
  "autoRenewing": false,
  ...
  "paymentState": 1  # Payment received
}

帳戶保留

帳戶保留是一種訂閱狀態,當使用者的付款方式失敗,而在相關的寬限期結束時款項未獲得解決,即開始進入此狀態。當訂閱項目進入帳戶保留狀態時,您應封鎖相關內容或服務的存取權。帳戶保留期限最長可達 30 天。

在帳戶保留期限內,BillingClient.queryPurchasesAsync() 不會傳回該訂閱項目。

在帳戶保留期限內,可以視需要處理任何取消還原或重新購買訂閱項目的操作。

當使用者進入帳戶保留狀態時,您應運用即時開發人員通知,通知使用者訂閱項目的存取遭停權的原因。您應在應用程式中提供訊息,說明如何修正付款以及重新取得該訂閱項目存取權的方式。訊息應包含 Google Play 訂閱設定的連結,以便使用者修正付款方式。例如,您可以使用類似以下的訊息:

"There is a problem with your subscription. Click here to go to the
Google Play subscription settings to fix your payment method."

如果使用者可以在應用程式外存取訂閱內容,建議您向使用者傳送推播通知或電子郵件,告知對方訂閱項目已失效。

如果客戶修正了付款問題,您可以在應用程式中顯示訊息,通知使用者訂閱項目已於何時還原。例如,您可以使用類似以下的訊息:

"Your form of payment was updated, and your subscription has
been recovered."

透過即時開發人員通知,當訂閱項目進入帳戶保留狀態時,您會收到類型為 SUBSCRIPTION_ON_HOLDSubscriptionNotification。從安全的後端伺服器呼叫 Google Play Developer API 以擷取新的訂閱資訊。在帳戶保留期間,訂閱資源expiryTimeMillis 會設定為過去的時間戳記,paymentState 會設定為 0

{
  "kind": "androidpublisher#subscriptionPurchase",
  ...
  "expiryTimeMillis": timestamp_in_past,
  "autoRenewing": true,
  ...
  "paymentState": 0  # Payment pending
}

使用者修正付款方式後,訂閱項目會恢復為活動狀態,接著您必須還原訂閱內容的存取權。

如果應用程式僅使用 queryPurchasesAsync() 來判斷使用者是否有權存取訂閱項目,應用程式需自動處理從帳戶保留狀態復原的訂閱項目。

如果應用程式會與伺服器同步訂閱狀態,則應監聽類型為 SUBSCRIPTION_RECOVEREDSubscriptionNotification,以便在復原訂閱項目時收到通知,而使用者則應重新取得存取權。如果您在收到這則通知後查詢訂閱,expiryTimeMillis 會設定為未來的時間戳記,而 paymentState 則為 1

{
  "kind": "androidpublisher#subscriptionPurchase",
  ...
  "expiryTimeMillis": timestamp_in_future,
  "autoRenewing": true,
  ...
  "paymentState": 1  # Payment received
}

如果使用者在帳戶保留期限結束前仍未修正付款方式,您會收到一個 SUBSCRIPTION_CANCELED 即時開發人員通知。如需處理取消訂閱的相關說明,請參閱取消訂閱。當您查詢以這種方式取消的訂閱項目時,傳回的 expiryTimeMillis 會設定為過去的時間戳記,而 cancelReason 的值則為 1

{
  "kind": "androidpublisher#subscriptionPurchase",
  ...
  "expiryTimeMillis": timestamp_in_past,
  "autoRenewing": false,
  ...
  "cancelReason": 1  # The system cancelled the subscription
}

寬限期

如果啟用了寬限期,而在帳單週期結束時出現付款問題,訂閱項目會進入寬限期。在這段期間,當 Google Play 嘗試續訂訂閲項目時,使用者仍可存取該訂閱項目。可以透過 Google Play 管理中心的應用程式內產品設定指定寬限期的長度。

如果應用程式僅使用 queryPurchasesAsync() 來判斷使用者是否有權存取訂閱項目,應用程式應自動處理寬限期,因爲 queryPurchasesAsync() 會在到期日之前繼續傳回取消的購買交易。

如果應用程式會與後端同步訂閱狀態,則應監聽類型為 SUBSCRIPTION_IN_GRACE_PERIODSubscriptionNotification,以便在使用者進入寬限期時收到通知。使用者在寬限期內時,訂閱資源會含有 autoRenewing = truepaymentState = 0(例如待處理)。

{
  "kind": "androidpublisher#subscriptionPurchase",
  ...
  "expiryTimeMillis": timestamp_in_future,
  "autoRenewing": true,
  ...
  "paymentState": 0  # Payment pending
}

當使用者進入寬限期時,應在應用程式中顯示訊息,讓使用者瞭解如何修正付款方式。否則,在寬限期結束時,使用者就無法再存取訂閱項目。這則訊息可以透過深層連結至 Google Play 商店,協助使用者管理訂閱項目。

使用者修正付款方式後,系統會續訂訂閱項目,而應用程式會依據續訂所述的方式處理續訂。

如果使用者在寬限期內未修正付款方式,訂閱項目就會進入帳戶保留狀態。

暫停提供的訂閱項目

您可以讓使用者暫停訂閱項目以避免自願性流失。啟用暫停功能時,使用者可以選擇將訂閱項目暫停一週至三個月,視循環週期而定。啟用暫停功能後,「暫停」選項會顯示在訂閱中心和取消流程中。請注意,按年的訂閱項目無法暫停,一週和三個月的暫停限制隨時有可能會變動。

若要讓使用者暫停訂閱項目,請執行下列步驟:

  1. 登入 Google Play 管理中心
  2. 選取您的應用程式,然後依序前往「商店發布」>「應用程式內產品」>「訂閱項目」。
  3. 展開「訂閱設定」專區。
  4. 勾選「允許暫停訂閱」。

目前的帳單週期結束後,訂閱項目暫停功能才會生效。訂閱項目暫停期間,使用者無法存取該訂閱項目。暫停期間結束後,訂閱就會恢復,Google 會嘗試續訂該訂閲項目。如果成功恢復訂閱,該訂閱項目就會再次生效。如果因付款問題而恢復失敗,使用者會進入帳戶保留狀態,如圖 1 所示:

使用者暫停訂閱項目,帳戶進入保留狀態
圖 1.使用者暫停訂閱項目,帳戶進入保留狀態。

使用者也可以選擇在暫停期間內,隨時手動恢復訂閱項目,如圖 2 所示。使用者手動恢復時,帳單日期會變更為手動恢復日期。

使用者暫停訂閱後再恢復訂閱項目
圖 2.使用者暫停訂閱後再恢復訂閱項目。

使用者暫停訂閱時,queryPurchasesAsync() 不會傳回訂閱項目。恢復訂閲後,queryPurchasesAsync() 會傳回該訂閱項目。

如果應用程式會與安全的後端伺服器同步訂閱狀態,則應監聽即時開發人員通知來維持狀態。這些通知也可讓您在應用程式中通知使用者他們已暫停訂閱項目,因而無法存取訂閱內容。您也應該提供使用者 Google Play 的深層連結,使其可以手動恢復訂閱項目。

使用者暫停訂閱項目時,系統會傳送類型為 SUBSCRIPTION_PAUSE_SCHEDULE_CHANGEDSubscriptionNotification。這時候使用者應保有訂閱項目的存取權,而訂閱資源則有 autoRenewing = truepaymentState = 1(已收到款項)以及 expiryTimeMillisautoResumeTimeMillis 的未來值。

暫停功能生效後,系統會傳送類型為 SUBSCRIPTION_PAUSEDSubscriptionNotification。此時使用者應再也無法存取訂閲項目,而訂閱資源則含有 autoRenewing = truepaymentState = 0(待處理)、autoResumeTimeMillis 的未來值以及 expiryTimeMillis 的過去值。

如果在暫停訂閲期結束時訂閱自動恢復,或是使用者選擇手動恢復訂閲,則系統會傳送類型為 SUBSCRIPTION_RENEWEDSubscriptionNotification。應依據續訂所述的方式處理這項操作。

如果在嘗試恢復訂閱時付款失敗,系統會傳送類型為 SUBSCRIPTION_ON_HOLDSubscriptionNotification。應依據帳戶保留章節所述的方式處理這項操作。

復原

取消的訂閱項目在到期日前仍會顯示在 Play 商店應用程式中,直到過期為止。使用者可以在 Google Play 商店應用程式中「訂閲項目」專區中,按一下「重新訂閲」(之前為「還原」),即可復原已取消的訂閱。

Google Play 商店應用程式中的訂閱項目專區,顯示了已取消的訂閱項目和重新訂閱按鈕
圖 3.Google Play 商店應用程式中的「帳戶」>「訂閱項目」專區,顯示了已取消的訂閱項目和「重新訂閲」按鈕。

如果應用程式僅使用 queryPurchasesAsync() 來判斷使用者是否有權存取訂閱項目,應用程式應自動處理訂閱的還原,因爲 queryPurchasesAsync() 會在到期日之前繼續傳回取消的購買交易。還原的訂閱項目會形同未曾被取消般繼續續訂。

如果應用程式會與後端同步訂閱狀態,則應監聽類型為 SUBSCRIPTION_RESTARTEDSubscriptionNotification。收到通知後,應用程式會回應通知,記錄訂閱項目現在已設定為續訂,並且停止在應用程式中顯示還原訊息。訂閱資源看起來類似如下:

{
  "kind": "androidpublisher#subscriptionPurchase",
  ...
  "expiryTimeMillis": expiry_time_in_future,
  "autoRenewing": true,
  ...
  "paymentState": 1  # Payment received
}

升級、降級和重新訂閱

當使用者升級降級,或在訂閲項目到期前從應用程式重新註冊時,舊的訂閱項目就會失效,系統會使用新的購買權杖建立新訂閱項目

此外,Google Play Developer API 傳回的訂閱資源將包含 linkedPurchaseToken,表示用戶要降級、升級或重新訂閲舊的購買交易。您可以使用 linkedPurchaseToken 查詢舊的訂閱項目,並識別現有的使用者帳戶,以便將新的購買交易連結至同一個帳戶。我們也建議您使用 Google Play Developer API 確認購買交易,以減少使用者操作不便的情形。訂閱資源看起來類似如下:

{
  "kind": "androidpublisher#subscriptionPurchase",
  ...
  "expiryTimeMillis": next_renewal_date,
  "autoRenewing": true,
  "linkedPurchaseToken": old_purchase_token
  ...
  "paymentState": 1  # Payment received
}

開發人員必須讓客戶能輕鬆管理訂閱項目。應用程式應具有設定或設定偏好的畫面連結,方便使用者管理訂閱項目。此連結的範例如圖 4 所示。

本圖中的「Google Play 訂閱服務」按鈕為「管理訂閱項目」連結的範例。
圖 4.「Google Play 訂閱服務」按鈕是「管理訂閱項目」的連結範例。

在這個連結的點擊處理常式中,新增邏輯來判斷使用者是否擁有應用程式任何未過期的訂閱項目,其中 expiryTimeMillis 是未來的日期,或是 autoRenewing 設定為 true

每個訂閱項目的 SKU 與您在 Play 管理中心建立訂閱項目時為其指定的產品 ID 相符。如要透過程式判斷現有訂閱項目的 SKU,請查詢應用程式的後端,取得與特定使用者相關的訂閱項目清單。

如果使用者有未過期的訂閱項目,您可以引導他們前往類似如下的網址,並且以訂閲項目 ID 和應用程式套件資訊替換「your-sub-product-id」和「your-app-package」:

https://play.google.com/store/account/subscriptions?sku=your-sub-product-id&package=your-app-package

如果使用者在應用程式中沒有任何未過期的訂閱項目,請使用下列網址引導他們前往顯示所有其他訂閲項目的頁面(如圖 5 和圖 6 所示):

https://play.google.com/store/account/subscriptions
Play 商店訂閱項目畫面顯示了使用者所有訂閱項目的狀態。
圖 5.Play 商店訂閱項目畫面顯示了使用者所有訂閱項目的狀態。
輕觸訂閱項目查看更多資訊。
圖 6.輕觸訂閱項目可以查看更多資訊。

您可以在 Classy Taxi 範例應用程式中找到訂閱項目連結邏輯的範例程式碼。

允許使用者升級、降級或變更訂閱項目

您可以向使用者提供不同的訂閱層級,例如基本級和進階級。圖 7 顯示提供兩個訂閱層級的畫面:

這個應用程式包含兩個訂閱層級
圖 7.這個應用程式有兩個訂閱層級。

使用者必須能夠存取與圖 7 類似的畫面,以升級或降級訂閱項目。升級或降級訂閲項目時,可以設定依比例計費模式,或是變更對訂閱者造成的影響。下表列出可使用的依比例計費模式:

依比例計費模式說明
IMMEDIATE_WITH_TIME_PRORATION 訂閱項目會立即升級或降級。根據費用差額調整任何剩餘時間,並將下一個帳單日期往後推延以計入新的訂閲。此為預設行為。
IMMEDIATE_AND_CHARGE_PRORATED_PRICE 系統會立即升級訂閲項目,帳單週期維持不變。系統會向使用者收取剩餘訂閱期間的費用差額。
IMMEDIATE_WITHOUT_PRORATION 系統會立即升級或降級訂閱項目,並在續訂訂閲項目時收取新的價格。帳單週期維持不變。
DEFERRED 只有在續訂時,系統才會升級或降級訂閲項目。
IMMEDIATE_AND_CHARGE_FULL_PRICE 系統將訂閲項目升級或降級,並立即向使用者收取新授權的全額費用。系統會將之前訂閲項目的剩餘價值,轉用於相同的授權,或者在切換至不同的授權時依比例計算時間。

依比例計費範例

若要瞭解各種依比例計費模式的運作方式,請考慮下列情境:

Samwise 訂閱了 Country Gardener 應用程式的線上內容。他目前按月訂閱該内容的「第 1 層級」版本(僅限文字內容)。這個訂閱項目的費用為「每月 2 美元」,並於每月第一天續訂。

4 月 15 日,Samwise 選擇升級為按年訂閲的「第 2 層級」版本,內容包含影片更新,費用為「每年 36 美元」。

升級該訂閱項目時,開發人員需選擇依比例計費模式。以下清單說明各種依比例計費模式對 Samwise 訂閱項目的影響:

IMMEDIATE_WITH_TIME_PRORATION
Samwise 的「第 1 層級」訂閱會立即結束。由於他支付了全額月費(4 月 1 日至 30 日),但在訂閱期間中途進行了升級,因此這個月一半的訂閱費用(1 美元)會套用到新訂閱項目。不過,由於新訂閱項目的費用為每年 36 美元,1 美元的抵免餘額只能用於支付 10 天(4 月 16 日至 25 日)的費用,因此在 4 月 26 日,系統會針對新訂閲項目向他收取 36 美元的費用,之後每年的 4 月 26 日再收取 36 美元。
IMMEDIATE_AND_CHARGE_PRORATED_PRICE
可以使用這種模式,因為第 2 層級每個時間單位的訂閲價格(每年 36 美元 = 每月 3 美元)高於每個時間單位的第 1 層級訂閲價格(每月 2 美元)。Samwise 的第 1 層級訂閱會立即結束。由於他支付了全額月費,但只使用了一半,因此這個月一半的訂閱費用(1 美元)會套用到新訂閱項目。不過,由於新訂閱項目的費用為每年 36 美元,剩餘 15 天的費用為 1.50 美元,因此系統會針對新訂閱項目向他收取 0.50 美元的差額。5 月 1 日系統會針對新的訂閲層級向 Samwise 收取 36 美元,並在之後每年的 5 月 1 日再收取 $36 美元。
IMMEDIATE_WITHOUT_PRORATION
Samwise 的第 1 層級訂閱會立即免費升級為第 2 層級,並且系統會針對新的訂閲層級向他收取 36 美元,之後每年的 5 月 1 日再收取 36 美元。
DEFERRED
Samwise 的第 1 層級訂閱繼續有效,直到 4 月 30 日到期爲止。5 月 1 日,第 2 層級訂閱生效,系統會針對新的訂閲層級向 Samwise 收取 36 美元。
IMMEDIATE_AND_CHARGE_FULL_PRICE
Samwise 的第 1 層級訂閱會立即結束。他的第 2 層級訂閱將於今天開始生效,費用為 36 美元。由於他支付了全額月費,但只使用了一半,因此這個月一半的訂閱費用(1 美元)會套用到新的訂閱項目。由於新訂閱項目的費用為每年 36 美元,因此訂閱期可再加上一年的 1/36(約 10 天)。因此,下次向 Samwise 收費的時間為從今天起 1 年零 10 天,費用為 36 美元。接下來,系統每年收取 36 美元的費用。

選擇依比例計費模式時,請務必查看我們的依比例計費建議

應用程式可以使用與推出購買流程相同的步驟,向使用者提供升級或降級服務。不過,在升級或降級時,您必須提供目前的訂閱項目、未來的(升級或降級)訂閱項目的詳細資料,以及使用的依比例計費模式的內容,如以下範例所示:

Kotlin

// Retrieve a value for "skuDetails" by calling querySkuDetailsAsync()
val flowParams = BillingFlowParams.newBuilder()
        .setSubscriptionUpdateParams(SubscriptionUpdateParams.newBuilder()
            .setOldSkuPurchaseToken(purchaseTokenOfOriginalSubscription)
            .setReplaceSkusProrationMode(desiredProrationMode))
        .setSkuDetails(upgradeOrDowngradeSkuDetails)
        .build();
val responseCode = billingClient.launchBillingFlow(activity, flowParams)

Java

// Retrieve a value for "skuDetails" by calling querySkuDetailsAsync()
BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
        .setSubscriptionUpdateParams(SubscriptionUpdateParams.newBuilder()
            .setOldSkuPurchaseToken(purchaseTokenOfOriginalSubscription)
            .setReplaceSkusProrationMode(desiredProrationMode))
        .setSkuDetails(upgradeOrDowngradeSkuDetails)
        // If the old subscription was created using an obfuscated account
        // id, you should use that value when setting the obfuscatedAccountId
        // here.
        .setObfuscatedAccountId(obfuscatedAccountId)
        .build();
int responseCode = billingClient.launchBillingFlow(billingFlowParams);

針對立即取代的依比例計費模式,應用程式會在 PurchasesUpdatedListener 中收到新的購買交易。BillingClient.queryPurchasesAsync() 中也會提供該購買交易。收到購買權杖後,請執行與驗證新的購買權杖相同的驗證程序。請務必透過 Google Play 帳款服務程式庫的 Purchases.subscriptions:acknowledge 或 Google Play Developer API 的 BillingClient.acknowledgePurchase() 確認這些購買交易。

Google Play Developer API 會在訂閱資源中傳回 linkedPurchaseToken。請務必讓 linkedPurchaseToken 中提供的權杖失效,以確保舊的權杖無法用來存取服務。請參閱升級、降級和重新訂閱,瞭解處理升級和降級購買的相關資訊。

針對延遲的取代模式,應用程式會收到一個對 PurchasesUpdatedListener 的呼叫與空白的購買交易清單,以及升級或降級是否成功的狀態。在取代模式生效前,BillingClient.queryPurchasesAsync() 會繼續傳回原有訂閱方案的購買交易。新的方案生效後,queryPurchasesAsync() 會傳回新訂閱項目的購買交易資料,並將 SUBSCRIPTION_RENEWED 通知傳送至安全的後端伺服器。針對延遲的取代模式,強烈建議您聽取這項通知,並使用 Purchases.subscriptions:acknowledge 確認購買。訂閱資源中的 linkedPurchaseToken 可用來判斷應將訂閱後端的哪位使用者(如適用)更新到新的授權。應用程式不應依賴使用者開啟應用程式並透過 BillingClient.acknowledgePurchase() 確認,因為使用者不一定會在方案變更生效後的三天內開啟應用程式。

透過免費試用或新用戶優惠升級

當使用者升級或降級時,系統會套用免費試用的資格設定。您可以在 Google Play 管理中心內調整免費試用資格設定。

請注意以下事項:

  • 如果在應用程式可提供的所有訂閲項目中,使用者只能獲得一次免費試用資格,則使用者變更的方案將不會享有免費試用或新用戶優惠。
  • 如果您為每個訂閱產品提供一次免費試用資格,則使用者變更的方案得以享有免費試用或新用戶優惠。

下表說明新舊方案均可享有免費試用、以及使用者在免費試用期内升級時,各種依比例計費模式的行爲:

每個應用程式免費試用一次 每個訂閱產品免費試用一次
IMMEDIATE_WITH_TIME_PRORATION 使用者會立即失去免費試用資格。系統會根據費用差額,將剩餘的免費試用期轉換為新訂閲層級的同等免費試用期。 使用者會失去先前的免費試用資格,但立即開始新的免費試用。此外,系統會將舊訂閲層級的剩餘免費試用期轉換為新訂閲層級的同等免費試用期,並加進新的免費試用期。
IMMEDIATE_AND_CHARGE_PRORATED_PRICE

使用者會立即失去免費試用資格。系統接著會向使用者收取剩餘訂閱期的費用差額。下次帳單日期將維持不變。

注意:這個選項僅適用於升級訂閱,亦即每個時間單位的費用增加。

IMMEDIATE_WITHOUT_PRORATION 使用者會立即升級至新訂閲層級。在上一次帳單週期結束前,使用者仍然可以免費試用新的訂閲層級。
延遲 在下次帳單日期之前,使用者仍然可以免費試用舊訂閲項目。
IMMEDIATE_AND_CHARGE_FULL_PRICE 使用者會立即失去免費試用資格。接著系統會向使用者收取新訂閱項目的費用。下次帳單日期是新的訂閱週期再加上免費試用期的剩餘時間。

為了瞭解在每個應用程式免費試用一次的模式中,免費試用期在預設情況下的轉換方式,請試想以下情境:

Maria 訂閱了 Country Gardener 應用程式的線上內容。她目前按月訂閱該内容的「第 1 層級」版本(僅限文字內容)。這個訂閱項目的費用為每月 10 美元,而她在 4 月 1 日訂閱了這個項目。身為首次訂閱者,她享有 30 天的免費試用期,因此 5 月 1 日需繳清第一筆款項。

4 月 15 日,Maria 選擇升級至第 2 層級的訂閱,內容包含影片更新,費用為每月 20 美元。第二次訂閱也可享受 30 天的試用期。

以下清單說明各種依比例計費模式的免費試用期轉換方式:

  • IMMEDIATE_WITH_TIME_PRORATION - Maria 的訂閱立即升級至第 2 層級。由於 Maria 在訂閱期中途進行了升級,因此這個月一半的訂閱費用(以每月 10 美元計算的 15 天費用)會套用到新的訂閱項目。不過,由於新訂閱項目的費用為每月 20 美元,因此這 15 天的餘額只能支付 7.5 天的費用。Maria 不符合免費試用第 2 層級的資格,因此自 4 月 22 日起,將會開始每月收取 20 美元。
  • IMMEDIATE_AND_CHARGE_PRORATED_PRICE可以使用這種模式,因為第 2 層級每個時間單位的訂閲價格(每月 20 美元)高於第 1 層級每個時間單位的訂閲價格(每月 10 美元)。Maria 的第 1 層級訂閱立即升級為第 2 層級,同時也失去免費試用資格。由於 Maria 的下次帳單日期是 5 月 1 日,因此今天她必須支付 4 月下半月的費用 10 美元,接著自 5 月 1 日起,每月將收取她 20 美元。
  • IMMEDIATE_WITHOUT_PRORATION - Maria 的第 1 層級訂閱立即升級為第 2 層級。Maria 可以免費試用至 4 月 30 日,而且現在可以存取第 2 層級的內容。自 5 月 1 日起,她每月必須支付 20 美元。
  • DEFERRED - Maria 的第 1 層級訂閲將持續至需繳交下一筆款項的 5 月 1 日。第 2 層級的訂閱將於 5 月 1 日生效,並在每個月的第一天向 Maria 收取 20 美元。
  • IMMEDIATE_AND_CHARGE_FULL_PRICE - Maria 的第 1 層級訂閱立即升級為第 2 層級,同時也失去免費試用資格。她今天將被收取 20 美元。由於 Maria 的免費試用期仍有 15 天,因此下次收費日期為今天起 1 個月 + 15 天後,也就是 7 月 1 日。自 7 月 1 日起,她每月必須支付 20 美元。

以下清單說明開發人員若允許每個訂閱項目免費試用一次時的轉換行爲:

  • IMMEDIATE_WITH_TIME_PRORATION - Maria 的訂閱立即升級至第 2 層級。由於 Maria 在訂閱期一半時升級,因此這個月一半的訂閱費用(以每月 10 美元計算的 15 天費用)會套用到新的訂閱。不過,由於新的訂閱項目費用為每月 20 美元,因此剩下的 15 天餘額只可支付 7.5 天的費用。Maria 符合免費試用第 2 層級的資格,因此她無須支付另外 37.5 天的費用。自 5 月 22 日起,每月將向她收取 20 美元。
  • IMMEDIATE_AND_CHARGE_PRORATED_PRICE可以使用這種模式,因為第 2 層級每個時間單位的訂閲價格(每月 20 美元)高於第 1 層級每個時間單位的訂閲價格(每月 10 美元)。Maria 的第 1 層級訂閱立即升級為第 2 層級,同時也失去免費試用資格。由於 Maria 下次帳單日期原為 5 月 1 日,因此今天她必須支付 4 月下半月的費用 10 美元,接著自 5 月 1 日起,每月將收取她 20 美元。
  • IMMEDIATE_WITHOUT_PRORATION - Maria 的第 1 層級訂閱立即升級為第 2 層級。在 4 月 30 日之前,Maria 可以免費試用,而且她現在可以存取第 2 層級的內容。
  • DEFERRED - Maria 可存取第 1 層級的訂閲內容,直到 5 月 1 日被收取下一筆款項為止。第 2 層級的訂閱將於 5 月 1 日生效,每個月的第一天將會向 Maria 收取 20 美元。
  • IMMEDIATE_AND_CHARGE_FULL_PRICE - Maria 的第 1 層級訂閱立即升級為第 2 層級,同時也失去免費試用資格。她今天將被收取 20 美元。由於 Maria 的免費試用期仍有 15 天,因此下次收費日期為今天起 1 個月 + 15 天後,也就是 7 月 1 日。自 7 月 1 日起,每月將向她收取 20 美元。

依比例計費的建議作法

下表列出依比例計費的不同情境,以及我們針對每個情境的推薦做法:

情境 推薦的依比例計費模式 結果
升級至價格更高的層級 IMMEDIATE_AND_CHARGE_PRORATED_PRICE 使用者立即取得存取權,並保留相同的收費週期。
降級至價格更低的層級 DEFERRED 使用者已支付價格更高的層級的費用,因此在下次帳單日期前仍可存取內容。
變更同一層級的重複週期(例如從按月訂閲變更為按年訂閲) DEFERRED 使用者將在下次帳單日期支付新的週期性費用。
在免費試用期內升級,保有免費試用資格 IMMEDIATE_WITHOUT_PRORATION 使用者保有免費試用資格,但在試用期的剩餘時間升級至更高的訂閲層級。
在免費試用期內升級 - 結束免費試用資格 IMMEDIATE_AND_CHARGE_PRORATED_PRICE 使用者會立即取得新訂閲層級的存取權,但不再享受免費試用資格。

流失後挽回

使用者取消訂閱項目後,您可以嘗試在應用程式中或透過 Play 商店挽回使用者。下表說明各種訂閱情境,以及相關的挽回動作和應用程式相關規定。

訂閲到期前 訂閱到期後
應用程式內 Play 商店中 應用程式內 Play 商店中
挽回功能 應用程式內訂閱項目 還原 應用程式內訂閱項目 重新訂閱
使用者完成結帳流程
使用者的訂閱項目仍對應到同一個 SKU 使用者可以訂閱相同或不同的 SKU 使用者可以訂閱相同或不同的 SKU
建立新的購買權杖
預設啟用 是,所有開發人員均須支援

沒有帳款服務程式庫 2.0 以上版本的應用程式:否

具有帳款服務程式庫 2.0 以上版本的應用程式:是。開發人員可以在管理中心選擇退出。

向使用者收費時

如果使用相同的 SKU:目前的帳單週期結束。

如果使用不同的 SKU:取決於依比例計費模式。

目前的帳單週期結束 立即 立即
必須實作 在應用程式中提供重新訂閱的 UI

偵測訂閱狀態變更

Play 商店的深層連結

在應用程式中提供重新訂閱的 UI 處理應用程式外購

訂閱到期前 - 應用程式內

對於已取消但尚未到期的訂閱項目,您可以讓訂閱者以與新訂閱者相同的應用程式內產品購買流程,還原應用程式中的訂閱項目。請確認 UI 會反映出使用者已有訂閱項目。例如,您可以考慮透過「重新啟用」按鈕,顯示使用者目前的到期日和週期性費用。

在多數情況下,您應考慮向使用者提供與其訂閲項目相同的價格和 SKU,如下所示:

  • 購買 SKU 相同的新訂閲項目。
  • 新訂閱項目會取代舊訂閱項目,並會在相同的到期日續訂。舊訂閱項目會立即標示為「已過期」。
  • 例如,Achilles 訂閱了 Example Music 應用程式,訂閱將於 8 月 1 日到期。7 月 10 日,他又重新訂閱了單月訂閲方案,每個月的價格不變。新訂閱立即生效,並使用了剩餘依比例計費的折抵金額,且依舊在 8 月 1 日續訂。

如要提供不同的價格(例如新的免費試用期或挽回折扣),您可以向該使用者提供不同的 SKU:

  • 依比例計費模式,用不同 SKU 執行升級或降級IMMEDIATE_WITHOUT_PRORATION
  • 新訂閱項目會取代舊訂閱項目,並會在相同的到期日續訂。在原有的到期日,將會向使用者收取新 SKU 的費用,包括任何的新用戶優惠價。如果舊訂閱項目是使用經過模糊處理的帳戶 ID 建立的,應將相同的 ID 傳遞至 BillingFlowParams 以執行升級和降級。
  • 例如,Achilles 訂閱了 Example Music 應用程式,訂閱將於 8 月 1 日到期。7 月 10 日,他又使用新用戶優惠重新訂閱了按年訂閱的方案。新訂閱方案立即生效,並且將於 8 月 1 日依新用戶優惠使用者收取費用。
  • 如果您決定在用於挽回的 SKU 中納入免費試用或新用戶優惠,請在 Google Play 管理中心取消勾選「允許每個應用程式免費試用一次」方塊,以確保使用者符合資格,這個選項會限制使用者每個應用程式只能取得一次免費試用。

收到購買權杖後,如同處理新訂閱項目一樣處理購買交易。另外,Google Play Developer API 會在訂閱資源中傳回 linkedPurchaseToken。請務必讓 linkedPurchaseToken 中提供的權杖失效,以確保舊的權杖無法用來存取服務。

訂閱到期前 - Play 商店中

當訂閲項目已取消但仍然有效時,使用者僅需按一下「重新訂閱」(之前為「還原」),即可在 Google Play 訂閱中心還原該訂閱項目。這樣就能保有相同的訂閱項目和購買權杖。

Google Play 商店應用程式中的訂閱項目專區,顯示了已取消的訂閱項目和重新訂閱按鈕
圖 8.Google Play 商店應用程式中的「帳戶」>「訂閱項目」專區,顯示了已取消的訂閱項目和「重新訂閲」按鈕。

若要進一步瞭解如何還原訂閱項目,請參閱還原

訂閱到期後 - 應用程式內

透過套用與新訂閱者相同的應用程式內產品購買流程,可讓已過期的訂閱者在應用程式內重新訂閲。請注意以下事項:

  • 若要向使用者提供折扣,建議您使用一個具有訂閱項目特價優惠的產品 ID 以及,也稱為挽回 SKU。您可以在應用程式中提供優惠,或在應用程式外(例如透過電子郵件)向使用者通知此優惠。
  • 若要訂閱一個挽回訂閱,請使用 Google Play 帳款服務資料庫在 Android 應用程式中啟動購買流程。這個流程與新訂閲項目相同,但您可以決定使用者可以使用的 SKU。
  • 如果您決定在用於挽回的 SKU 中納入免費試用或新用戶優惠,請在 Google Play 管理中心取消勾選「允許每個應用程式免費試用一次」方塊,以確保使用者符合資格,這個選項會限制使用者每個應用程式只能取得一次免費試用。
  • 如果使用者重新訂閱相同的 SKU,則不符合免費試用或新用戶優惠的資格。請確認 UI 能反映出這些資訊。

收到購買權杖後,如同處理新訂閱項目一樣處理購買交易。您將不會在訂閱資源中收到 linkedPurchaseToken

訂閱到期後 - Play 商店中

如果是啟用的狀態,使用者在 Google Play 訂閱中心按一下「重新訂閱」,即可在到期後重新訂閱相同的 SKU,最長可訂閲一年。系統會產生新的訂閱項目和購買權杖。

Google Play 商店應用程式中的訂閱項目專區,顯示已取消和已過期的訂閱項目以及重新訂閱和移除按鈕
圖 9.Google Play 商店應用程式中的「帳戶」>「訂閱項目」專區,顯示了已取消和已過期的訂閱項目,並提供「重新訂閱」和「移除」按鈕。

重新訂閱視為應用程式外購行為,因此請務必遵循處理在應用程式外進行的購買交易的最佳做法。

客戶管理

在使用即時開發人員通知下,您可以即時得知使用者何時決定取消訂閱。當使用者在到期前取消訂閱,您可以傳送推播通知或應用程式內通訊訊息,請求使用者重新訂閱。詳情請參閱流失後挽回

免費試用與新用戶優惠

應用程式可以提供免費試用與新用戶優惠,鼓勵客戶試用您的應用程式。

免費試用

您可以讓使用者嘗試先訂閲,後付款。免費試用可執行一段您指定的時間,並在免費試用期結束後自動轉換成完整的訂閱。轉換後的訂閱項目採用與一般訂閲項目相同的時間範圍和價格。您可以為所有類型的訂閱項目設定免費試用期。

若要開始免費試用,使用者需在 Google Play 完成標準的訂閱購買程序。如果使用者符合免費試用資格,在免費試用期內無須付費,並且系統會透過電子郵件通知使用者的訂閱項目含有免費試用期。Google Play 會將這筆交易標示為 0.00 美元;在免費試用期間或使用者取消訂閱前,訂閱項目均會標示為「已購買」。

在開始免費試用之前,Google Play 會驗證使用者擁有有效的付款方式。部分使用者可能會將這樣的驗證認為是「暫緩付款」或「扣款」。這筆暫緩付款或扣款只是暫時性的,稍後會退還或退款。

試用期結束後,系統會向使用者的付款方式收取全額訂閱費用。

如果使用者在免費試用期內隨時取消訂閱,在試用期結束前訂閱項目仍然有效,而且免費試用期結束時,系統不會向使用者收取費用。

根據預設,在應用程式所提供的所有訂閲項目中,使用者只能享有一次免費試用或新用戶優惠。若要為每項訂閱產品提供一次免費試用或新用戶優惠,您可以在 Google Play 管理中心變更相關設定。

若要為訂閱項目新增免費試用,請參閱 Google Play 說明中心的免費試用說明

對於提供免費試用的訂閱項目,其訂閱生命週期事件的運作方式與不提供免費試用的訂閲項目相同。唯一的差別在於續訂期與標準訂閱項目的續訂間隔不同。

向使用者展示可銷售的產品時,可以使用 SkuDetails.getFreeTrialPeriod() 方法展示該產品提供了免費試用。

如果訂閱項目是透過免費試用購買而來,從 Google Play Developer API 傳回的訂閱項目中會包含 paymentState = 2(免費試用)。如果該訂閲項目已成功續訂,paymentState 會切換為 1(已收到款項)。

新用戶優惠

與免費試用類似,應用程式可提供新用戶優惠以吸引使用者試用您的應用程式。若要進一步瞭解新用戶優惠及其啟用方式,請參閱建立訂閱項目

對於提供新用戶優惠的訂閱項目,其訂閱生命週期事件的運作方式與不提供新用戶優惠的訂閲項目相同。唯一的差別在於續訂期與標準訂閱項目的續訂間隔可能不同。

向使用者展示可銷售的產品時,可以使用 SkuDetails.getIntroductoryPrice() 和相關方法向使用者表明訂閲項目提供新用戶優惠。

宣傳您的訂閱項目

您可以建立促銷代碼,為選取的使用者延長現有訂閲 SKU 的免費試用期。如要瞭解詳情,請參閱促銷代碼

取消、退款或撤銷

您可以使用 Google Play Developer API 取消退款撤銷訂閱項目。Google Play 管理中心也提供這項功能。

  • 取消:使用者可以在 Google Play 取消訂閱項目。您也可以提供選擇,讓使用者在應用程式中或網站上取消訂閲。應用程式應依據撤銷所述處理這些取消操作。
  • 退款:退款後,使用者可以繼續使用該訂閱項目。例如,如果有技術錯誤導致使用者無法存取您的產品,但錯誤已得到解決,則可以使用退款功能。請注意,如果退款金額超過最近支付的款項,或者如果想要進行部分退款,您必須使用 Google Play 管理中心。
  • 撤銷:撤銷後,使用者將立即失去該訂閲項目的存取權。例如,如果有技術錯誤導致使用者無法存取您的產品,而且使用者不想繼續使用該產品,則可以使用此功能。應用程式應依據撤銷所述處理這些取消操作。

下表說明取消、退款與撤銷之間的差異。

停止續訂 退還款項 撤銷存取權
取消
退款
撤銷

延後向訂閱者收費

您可以在 Google Play Developer API 中使用 Purchases.subscriptions:defer 將訂閱者的下次帳單日期往後推。在延後期間,使用者可完整存取訂閱的內容,但無須支付費用。系統將根據新的日期來更新續訂日期。

延後帳單功能可讓您執行下列動作:

  • 讓使用者免費存取以作爲特別優惠,例如購買影片可免費享有一週的觀影體驗。
  • 提供使用者免費存取以表達善意。

每個 API 呼叫可以將帳單最短延後一天,最長延後一年。若要將收費時間延得更長,您可以在新的收費日期前再次呼叫 API。

舉例來說,Darcy 按月訂閲 Fishing Quarterly 應用程式的線上內容。系統通常會在每月第一天向她收取 1.25 英鎊。3 月時她參與了應用程式發布者的線上問卷調查。發布者將下次付款日期延後至 5 月 15 日(也就是原定帳單日期 4 月 1 日後六個星期),以作為免費 6 周的獎勵。4 月或 5 月初,Darcy 無須支付費用且仍可存取相關內容。5 月 15 日,她支付了該月 1.25 英鎊的正常訂閱費用。下次續訂日期變為 6 月 15 日。

延後時,您可以考慮透過電子郵件或在應用程式內通知使用者其帳單日期已變更。

調整訂閲價格

警告:請勿調整透過 Google 訂閱的訂閲價格。

Google Play 可讓您向全球不同地區的使用者販售數位產品,他們使用不同的貨幣,價格考量也各不相同。有時,由於區域成本或貨幣波動,您可能會決定調整訂閲價格。如果您願意沿用現有訂閱者的目前價格,可以使用更新的價格建立新的 SKU,並將該 SKU 提供給新的訂閱者。

如果您無法繼續向訂閱者提供他們在訂閲時的價格,並且願意讓決定不接受新價格的使用者取消訂閱,您可以強制執行價格異動。如果使用者不同意新價格,系統就會取消他們的訂閱項目。為了盡量提高加入率,並鼓勵使用者採取行動,應用程式應向使用者顯示即將開始的價格異動的相關訊息。若要進一步瞭解價格異動,請參閱通知價格異動

請執行下列操作調整訂閱項目的價格,:

  1. 登入 Google Play 管理中心
  2. 找到具有您要調整價格的訂閲項目的應用程式。
  3. 依序選取「商店發布」>「應用程式內產品」,然後開啟「訂閱項目」分頁標籤。
  4. 選取您要調整的價格旁邊的「編輯」連結,如圖 10 所示:

    編輯訂閲價格欄位
    圖 10.編輯訂閲價格欄位。
  5. 輸入新的訂閲價格。

  6. 調整價格時,系統會顯示確認對話方塊,如圖 11 所示。

    編輯訂閲價格時會顯示一則警告
    圖 11.編輯訂閲價格時,系統會顯示一則警告。

    這個對話方塊說明價格異動對新訂閱者和現有訂閱者的影響。請注意以下事項:

    • 一旦確認,您就無法撤銷價格異動。
    • Google Play 會在確認後 7 天開始通知使用者價格異動。
    • 調漲訂閲價格時,使用者必須在 30 天內核准價格異動,否則系統就會自動取消他們的訂閱項目。
    • 對於現有訂閱者,系統會在他們的下次續訂日期時自動調降訂閲價格。降價後訂閲的所有者會自動享有調降的價格。

    按一下「套用」繼續。

  7. 系統會顯示確認對話方塊,再次說明新的訂閲價格的生效時間。

    顯示訂閲價格異動生效時間的確認對話方塊
    圖 12.顯示訂閲價格異動生效時間的確認對話方塊。

向使用者通知價格異動

建議您在調整價格時通知現有訂閱者,尤其是在調漲價格時。

當您調漲訂閲價格時,在 Google Play 開始通知價格異動前,您有至少 7 天的時間通知現有訂閱者有關這項調價。Google Play 通知使用者時,系統會顯示類似於圖 13 所示的對話方塊。此對話方塊顯示舊價格、新價格及新價格生效的日期。

用於通知使用者訂閲價格異動的一般對話方塊
圖 13.用於通知使用者訂閲價格異動的一般對話方塊。

在應用程式中,可以透過下列方式顯示這個對話方塊:

可透過查看訂閱資源中的 priceChange 欄位,判斷使用者是否有待處理的價格異動。如果有,這個欄位會顯示訂閱項目出現價格異動,priceChange.state 欄位會指出使用者已接受還是仍未處理價格異動。

啟動價格異動確認流程

若要在應用程式啟動時顯示 Google Play 價格異動對話方塊,請使用 BillingClient.launchPriceChangeConfirmationFlow()

顯示價格異動對話方塊前,您也可以顯示自己的訊息或對話方塊,說明價格異動的原因。如果您建立並顯示這類的自訂訊息,使用者會較願意以新的價格續訂訂閱項目。

啟動價格異動確認流程的範例如下:

Kotlin

val priceChangeFlowParams = PriceChangeFlowParams.newBuilder()
        .setSkuDetails(changedPriceSubscriptionSkuDetails)
        .build()

billingClient.launchPriceChangeConfirmationFlow(activity,
        priceChangeFlowParams,
        object : PriceChangeConfirmationListener() {
            override fun onPriceChangeConfirmationResult(responseCode: Int) {
                if (responseCode == BillingResponseCode.OK) {
                    // User has confirmed the price change.
                } else if (responseCode == BillingResponseCode.USER_CANCELED) {
                    // User hasn't confirmed the price change and should retain
                    // access until the end of the current billing cycle.
                }
            }
        })

Java

PriceChangeFlowParams priceChangeFlowParams = PriceChangeFlowParams.newBuilder()
        .setSkuDetails(changedPriceSubscriptionSkuDetails)
        .build();

billingClient.launchPriceChangeConfirmationFlow(activity,
        priceChangeFlowParams,
        new PriceChangeConfirmationListener() {
            @Override
            public void onPriceChangeConfirmationResult(int responseCode) {
                if (responseCode == BillingResponseCode.OK) {
                    // User has confirmed the price change.
                } else if (responseCode == BillingResponseCode.USER_CANCELED) {
                    // User hasn't confirmed the price change and should retain
                    // access until the end of the current billing cycle.
                }
            }
        });

處理使用者確認價格異動的操作

如果使用者接受訂閱項目的新價格,系統會進行續訂,處理方式與任何其他續訂操作一樣。此外,您會收到類型為 SUBSCRIPTION_PRICE_CHANGE_CONFIRMEDSubscriptionNotification

價格異動遭到拒絕時的處理方式

如果在舊的訂閲項目到期前使用者尚未接受價格異動,他們的訂閱會被取消,並且您會收到類型為 SUBSCRIPTION_CANCELEDSubscriptionNotification。可依據取消訂閱中所述的方式處理這個事件。

意外價格異動

如果您意外調整了訂閲項目的價格,請立即撤銷價格異動。只要價格在 7 天內恢復,現有的訂閱者就不會收到意外價格異動的通知。請注意,在價格首次異動與價格恢復前的這個期間,新訂閱者可能會得到意外的價格。

連續進行兩次價格調整

請確保您一次只調整一個訂閲價格。我們不建議您基於測試目的調整價格。

如果您在 7 天內調整訂閲價格兩次,使用者只需同意最新的價格異動。

如果調整價格的間隔超過 7 天,則價格異動不會互相取消。反之,使用者必須同意第一次價格異動,並且具有享有第一個價格的續訂週期。該續訂週期結束之後,即可開始依第二個價格收費。接著系統每個月會依第二個價格收費。

處理付款遭拒問題

如在帳單週期結束時發生付款問題,在取消訂閲項目之前,Google 會定期嘗試該項續訂一段時間。重試期限最長可達 30 天,再加上任何指定的寬限期長度。在這段時間內,Google 也會傳送電子郵件和通知,請使用者更新付款方式。

付款遭拒時,訂閱項目會先進入寬限期 (如果有啟用)。在寬限期內,使用者仍可存取該訂閱項目。

寬限期結束時,訂閱項目進入帳戶保留狀態,最長可達 30 天。在帳戶保留期內,您可以封鎖訂閱項目的存取權。

若要在付款遭拒時盡量恢復訂閱項目,您可以通知使用者付款問題,並請對方修正。

可依據寬限期帳戶保留章節所述的方式自行執行這項操作,或者實作應用程式內的通訊 API,在該 API 中 Google 會向應用程式的使用者顯示一則訊息。

應用程式內通訊

如果您透過 InAppMessageCategoryId.TRANSACTIONAL 啟用應用程式內通訊功能,Google Play 會在寬限期和帳戶保留期內向使用者顯示訊息(每天顯示一次),讓使用者不必離開應用程式就能修正付款問題。

Snackbar 通知使用者修正付款問題
圖 14. Snackbar 通知使用者修正付款問題。

我們建議您在使用者每次開啟應用程式時呼叫此 API,以判斷是否應顯示訊息。

如果使用者成功復原訂閱項目,您會收到 SUBSCRIPTION_STATUS_UPDATED 的回應代碼和購買權杖。接下來,請使用這個購買權杖呼叫 Google Play Developer API,並在應用程式中重新整理訂閱狀態。

整合應用程式內通訊功能

若要向使用者顯示應用程式內通訊訊息,請使用 BillingClient.showInAppMessages()

以下是觸發應用程式內訊息流程的範例:

Kotlin

val inAppMessageParams = InAppMessageParams.newBuilder()
        .addInAppMessageCategoryToShow(InAppMessageCategoryId.TRANSACTIONAL)
        .build()

billingClient.showInAppMessages(activity,
        inAppMessageParams,
        object : InAppMessageResponseListener() {
            override fun onInAppMessageResponse(inAppMessageResult: InAppMessageResult) {
                if (inAppMessageResult.responseCode == InAppMessageResponseCode.NO_ACTION_NEEDED) {
                    // The flow has finished and there is no action needed from developers.
                } else if (inAppMessageResult.responseCode == InAppMessageResponseCode.SUBSCRIPTION_STATUS_UPDATED) {
                    // The subscription status changed. For example, a subscription
                    // has been recovered from a suspend state. Developers should
                    // expect the purchase token to be returned with this response
                    // code and use the purchase token with the Google Play
                    // Developer API.
                }
            }
        })

Java

InAppMessageParams inAppMessageParams = InAppMessageParams.newBuilder()
        .addInAppMessageCategoryToShow(InAppMessageCategoryId.TRANSACTIONAL)
        .build();

billingClient.showInAppMessages(activity,
        inAppMessageParams,
        new InAppMessageResponseListener() {
            @Override
            public void onInAppMessageResponse(InAppMessageResult inAppMessageResult) {
                if (inAppMessageResult.responseCode == InAppMessageResponseCode.NO_ACTION_NEEDED) {
                    // The flow has finished and there is no action needed from developers.
                } else if (inAppMessageResult.responseCode == InAppMessageResponseCode.SUBSCRIPTION_STATUS_UPDATED) {
                    // The subscription status changed. For example, a subscription
                    // has been recovered from a suspend state. Developers should
                    // expect the purchase token to be returned with this response
                    // code and use the purchase token with the Google Play
                    // Developer API.
                }
            }
        });