Vòng đời của gói thuê bao

Các giao dịch mua gói thuê bao có thể trải qua một số trạng thái trong suốt vòng đời, tuỳ thuộc vào nhiều yếu tố trong đó có hành vi tự động gia hạn, trường hợp từ chối thanh toán, và hành động quản lý của nhà phát triển.

Xử lý vòng đời của gói thuê bao tự động gia hạn

Khi trạng thái gói thuê bao của người dùng thay đổi, máy chủ phụ trợ của bạn sẽ nhận được thông báo SubscriptionNotification

Hình 1. Các trạng thái vòng đời và sự kiện chuyển đổi của giao dịch mua gói thuê bao tự động gia hạn.

Để cập nhật trạng thái trong phần phụ trợ, hãy gọi API purchases.subscriptionsv2.get kèm theo mã thông báo giao dịch mua trong thông báo. Điểm cuối này cung cấp trạng thái mới nhất của gói thuê bao, căn cứ vào mã thông báo giao dịch mua và được coi là nguồn đáng tin cậy để quản lý gói thuê bao.

Mã thông báo giao dịch mua có hiệu lực kể từ thời điểm đăng ký gói thuê bao cho đến hết 60 ngày sau khi gói thuê bao hết hạn. Sau ngày này, mã thông báo giao dịch mua sẽ không còn hợp lệ để gọi API Nhà phát triển Google Play.

Giao dịch mua gói thuê bao mới tự động gia hạn

Khi người dùng mua gói thuê bao, thông báo SubscriptionNotification thuộc loại SUBSCRIPTION_PURCHASED sẽ được gửi đến máy khách RTDN. Dù bạn nhận được thông báo này hay bạn đăng ký giao dịch mua mới trong ứng dụng thông qua PurchasesUpdatedListener hoặc tìm nạp giao dịch mua theo cách thủ công trong phương thức onResume() của ứng dụng, bạn đều cần phải xử lý giao dịch mua mới trong phần phụ trợ bảo mật. Để thực hiện việc này, hãy làm theo các bước sau:

  1. Truy vấn điểm cuối purchases.subscriptionsv2.get để lấy tài nguyên gói thuê bao có chứa trạng thái mới nhất của gói thuê bao.
  2. Hãy đảm bảo giá trị của trường subscriptionStateSUBSCRIPTION_STATE_ACTIVE.
  3. Xác minh giao dịch mua.
  4. Cấp cho người dùng quyền truy cập vào nội dung. Bạn có thể dùng đối tượng ExternalAccountIdentifiers từ tài nguyên gói thuê bao để xác định tài khoản người dùng liên kết với giao dịch mua nếu giá trị nhận dạng được đặt tại thời điểm mua hàng bằng setObfuscatedAccountIdsetObfuscatedProfileId.

Thư viện Play Billing cũng có một phương thức để xác nhận gói thuê bao, đó là acknowledgePurchase(), cũng như một phương thức để kiểm tra trạng thái xác nhận, đó là isAcknowledged(). Tuy nhiên, bạn nên xử lý quy trình mua hàng trong phần phụ trợ để tăng tính bảo mật.

Tài nguyên gói thuê bao của các giao dịch mua mới sẽ có dạng như trong ví dụ sau:

{
  "kind": "androidpublisher#subscriptionPurchaseV2",
  "startTime": "2022-04-22T18:39:58.270Z",
  "regionCode": "US",
  "subscriptionState": "SUBSCRIPTION_STATE_ACTIVE",
  "latestOrderId": "GPA.3333-4137-0319-36762",
  "acknowledgementState": "ACKNOWLEDGEMENT_STATE_PENDING", // need to acknowledge new purchases
  "lineItems": [
    {
      "productId": "sub_variant_plan01",
      "expiryTime": next_renewal_date,
      "autoRenewingPlan": {
        "autoRenewEnabled": true
      }
    }
  ],
}

Gia hạn gói thuê bao

Hệ thống sẽ gửi một thông báo SUBSCRIPTION_RENEWED khi gói thuê bao tự động gia hạn được gia hạn. Hãy đảm bảo người dùng vẫn có quyền sử dụng gói thuê bao, sau đó cập nhật trạng thái gói thuê bao bằng expiryTime mới được cung cấp trong tài nguyên gói thuê bao mà hệ thống trả về từ API Nhà phát triển Google Play. Tài nguyên gói thuê bao sẽ có dạng như trong ví dụ sau:

{
  "kind": "androidpublisher#subscriptionPurchaseV2",
  "startTime": "2022-04-22T18:39:58.270Z",
  "regionCode": "US",
  "subscriptionState": "SUBSCRIPTION_STATE_ACTIVE",
  "latestOrderId": "GPA.3333-4137-0319-36762",
  "acknowledgementState": "ACKNOWLEDGEMENT_STATE_ACKNOWLEDGED",
  "lineItems": [
    {
      "productId": "sub_variant_plan01",
      "expiryTime": next_renewal_date,
      "autoRenewingPlan": {
        "autoRenewEnabled": true
      }
    }
  ]
}

Bạn không cần xác nhận việc gia hạn gói thuê bao.

Thời gian ân hạn

Nếu có vấn đề về thanh toán khi gia hạn gói thuê bao, Google sẽ thông báo cho người dùng và định kỳ cố gắng gia hạn gói thuê bao trong một thời gian trước khi gói thuê bao đó hết hạn. Thời gian khôi phục có thể bao gồm thời gian ân hạn, sau đó là thời gian tạm ngưng tài khoản. Trong thời gian ân hạn này, người dùng vẫn được hưởng các quyền của gói thuê bao.

Phương thức queryPurchasesAsync() sẽ tiếp tục trả về các giao dịch mua đang trong thời gian ân hạn. Nếu ứng dụng của bạn chỉ dựa vào queryPurchasesAsync để kiểm tra xem người dùng có quyền truy cập vào gói thuê bao hay không, thì ứng dụng sẽ tự động xử lý thời gian ân hạn, vì các gói thuê bao này sẽ hiển thị là đang hoạt động thông qua Thư viện Play Billing.

Việc đồng bộ hoá trạng thái gói thuê bao với phần phụ trợ sẽ giúp bạn nắm rõ hơn về các trường hợp từ chối thanh toán và có thêm căn cứ khi tìm cách giảm tỷ lệ rời bỏ không tự nguyện. Hãy theo dõi các thông báo SubscriptionNotification thuộc loại SUBSCRIPTION_IN_GRACE_PERIOD để biết khi nào người dùng chuyển sang thời gian ân hạn. Khi người dùng đang trong thời gian ân hạn, tài nguyên gói thuê bao sẽ chứa autoRenewEnabled = true. Google Play sẽ kéo dài giá trị expiryTime một cách linh động cho đến khi thời gian ân hạn kết thúc vì quyền truy cập sẽ có hiệu lực cho đến khi người dùng huỷ hoặc khi hết thời gian ân hạn tối đa. Giá trị của trường subscriptionState trong khoảng thời gian này là SUBSCRIPTION_STATE_IN_GRACE_PERIOD. Tài nguyên gói thuê bao sẽ có dạng như trong ví dụ sau:

{
  "kind": "androidpublisher#subscriptionPurchaseV2",
  ...
  "subscriptionState": "SUBSCRIPTION_STATE_IN_GRACE_PERIOD",
  ...
  "lineItems": [
    {
      "productId": "sub_variant_plan01",
      "expiryTime": timestamp_in_future,
      "autoRenewingPlan": {
        "autoRenewEnabled": true
      }
    }
  ],
}

Play sẽ thông báo cho người dùng đang trong thời gian ân hạn rằng khoản thanh toán của họ đã bị từ chối và nhắc họ khắc phục vấn đề liên quan đến phương thức thanh toán trên Cửa hàng Play. Khi người dùng chuyển sang thời gian ân hạn, bạn cũng nên khuyến khích họ sửa lại phương thức thanh toán phòng khi thanh toán không thành công là trường hợp không tự nguyện. Một cách đơn giản để thực hiện việc này là sử dụng API Gửi thông báo trong ứng dụng. Nếu bạn gọi API này khi người dùng mở ứng dụng, họ sẽ thấy một thông báo trên Play trong thanh thông báo nhanh tạm thời cho người dùng biết rằng giao dịch thanh toán của họ đã bị từ chối. Thông báo này cũng bao gồm một đường liên kết sâu để người dùng sửa lại phương thức thanh toán của họ trên Google Play.

Ngay sau khi người dùng sửa lại phương thức thanh toán, gói thuê bao sẽ gia hạn với ngày gia hạn ban đầu. Bạn có thể xử lý lần gia hạn đó như mô tả trong phần Gia hạn.

Nếu người dùng không sửa lại phương thức thanh toán trong thời gian ân hạn, thì gói thuê bao sẽ chuyển sang trạng thái tạm ngưng tài khoản và họ sẽ mất quyền sử dụng.

Chuyển sang thời gian ân hạn và khôi phục

Hình 2 cho thấy dòng thời gian của một gói thuê bao chuyển sang thời gian ân hạn, sau đó khôi phục khi người dùng sửa lại phương thức thanh toán. Sau khi thời gian ân hạn kết thúc, người dùng sẽ mất các lợi ích của gói thuê bao và chuyển sang trạng thái tạm ngưng tài khoản.

Hình 2. Dòng thời gian của một gói thuê bao bước vào thời gian ân hạn và khôi phục trước khi thời gian ân hạn kết thúc.

Bạn cần nhớ những điểm sau đây:

  • Trong thời gian ân hạn, người dùng vẫn có quyền sử dụng các lợi ích của gói thuê bao.
  • Khi gói thuê bao khôi phục trong thời gian ân hạn, ngày gia hạn sẽ không được đặt lại.
  • Nếu bạn tăng thời gian ân hạn (ví dụ: từ 7 ngày lên 14 ngày) thì những người dùng đang trong thời gian ân hạn sẽ được tiếp tục sử dụng được các lợi ích của gói thuê bao.
  • Nếu bạn giảm thời gian ân hạn, những người dùng đã trải qua một khoảng thời gian đủ để vượt quá thời gian ân hạn mới sẽ bị thu hồi các lợi ích của gói thuê bao ngay lập tức. Ví dụ: nếu bạn giảm thời gian ân hạn từ 14 ngày xuống còn 7 ngày, thì những người dùng đang ở trong khoảng thời gian từ 8 đến 14 ngày của thời gian ân hạn cũ sẽ bị thu hồi các lợi ích của gói thuê bao ngay lập tức.

Thời gian ân hạn ngầm

Bạn có thể đặt thời gian ân hạn là 0 ngày, nhưng Play sẽ đợi tối thiểu 1 ngày nhằm đảm bảo người dùng có đủ thời gian để thử thanh toán lại. Thời gian ân hạn ngầm này cung cấp một mạng lưới an toàn cho quá trình xử lý thanh toán. Trong thời gian 24 giờ này, gói thuê bao vẫn duy trì trạng thái ACTIVE.

Cách tốt nhất để bạn luôn nắm bắt được các thay đổi về trạng thái gói thuê bao là lắng nghe và phản hồi các thông báo theo thời gian thực dành cho nhà phát triển (RTDN). Hãy gọi phương thức purchases.subscriptionsv2.get() tại thời điểm RTDN thay vì thời gian hết hạn để có được trạng thái chính xác hơn của gói thuê bao.

Tuỳ thuộc vào trạng thái của gói thuê bao sau thời gian ân hạn ngầm 24 giờ, bạn sẽ nhận được một trong các thông báo sau:

  • SUBSCRIPTION_ON_HOLD (nếu được bật)
  • SUBSCRIPTION_CANCELED (nếu bị huỷ)
  • SUBSCRIPTION_EXPIRED (nếu hết hạn)
  • SUBSCRIPTION_RENEWED (nếu gia hạn thành công)

Bạn cũng có thể gọi phương thức subscriptionV2.get() bất cứ lúc nào sau thời gian ân hạn ngầm 24 giờ để nhận trạng thái mới nhất của gói thuê bao.

Tạm ngưng tài khoản

Nếu có vấn đề về thanh toán khi gia hạn gói thuê bao, thì sau khi kết thúc thời gian ân hạn, thời gian tạm ngưng tài khoản sẽ bắt đầu. Khi một gói thuê bao chuyển sang trạng thái tạm ngưng tài khoản, bạn phải chặn người dùng để họ sẽ không còn được hưởng quyền sử dụng gói thuê bao đó.

Trong thời gian tạm ngưng tài khoản, bạn cần tiếp tục xử lý mọi yêu cầu huỷ, yêu cầu khôi phục, hoặc yêu cầu mua lại gói thuê bao như thông thường, vì người dùng có thể thực hiện những thay đổi này trong khi gói thuê bao bị tạm ngưng.

RTDN thông báo cho bạn khi người dùng bước vào khoảng thời gian tạm ngưng tài khoản. Nhờ đó, bạn có thể thông báo cho họ càng sớm càng tốt về lý do họ bị tạm ngưng quyền truy cập vào gói thuê bao. Một cách đơn giản để thực hiện việc này là sử dụng API Gửi thông báo trong ứng dụng. Nếu gọi API này khi người dùng mở ứng dụng, họ sẽ nhìn thấy thông báo trong thanh thông báo nhanh tạm thời cho biết khoản thanh toán của họ đã bị từ chối. Thông báo này cũng bao gồm một đường liên kết sâu để người dùng sửa lại phương thức thanh toán của họ trên Google Play.

Nếu người dùng có thể truy cập vào nội dung gói thuê bao bên ngoài ứng dụng của bạn, thì họ có thể phát hiện ra rằng họ đã mất quyền truy cập trên nhiều nền tảng. Bạn nên gửi thông báo đẩy hoặc email cho người dùng để họ biết rằng gói thuê bao của họ không còn hoạt động do bị từ chối thanh toán.

Phương thức queryPurchasesAsync() sẽ không trả về gói thuê bao trong thời gian tạm ngưng tài khoản. Vì vậy, nếu ứng dụng của bạn dựa vào phương thức này để hiển thị các giao dịch mua hiện có, thì bạn nên hỗ trợ theo mặc định tính năng tạm ngưng tài khoản.

Trong Thông báo theo thời gian thực dành cho nhà phát triển, bạn sẽ nhận được một SubscriptionNotification thuộc loại SUBSCRIPTION_ON_HOLD khi gói thuê bao chuyển sang trạng thái tạm ngưng tài khoản. Gọi phương thức purchases.subscriptionsv2.get từ máy chủ phụ trợ bảo mật của bạn để truy xuất thông tin mới về gói thuê bao. Trong thời gian tạm ngưng tài khoản, trường expiryTime của tài nguyên gói thuê bao được đặt thành một dấu thời gian trong quá khứ, còn trường subscriptionState được đặt thành SUBSCRIPTION_STATE_ON_HOLD:

{
  "kind": "androidpublisher#subscriptionPurchaseV2",
  ...
  "subscriptionState": "SUBSCRIPTION_STATE_ON_HOLD",
  ...
  "lineItems": [
    {
      "productId": "sub_variant_plan01",
      "expiryTime": timestamp_in_past,
      ...
    }
  ],
}

Để khôi phục quyền truy cập, người dùng phải sửa lại phương thức thanh toán. Play sẽ thông báo cho người dùng có tài khoản bị tạm ngưng về việc bị từ chối thanh toán và bạn cũng nên khuyến khích họ sửa lại phương thức thanh toán.

Sau khi người dùng sửa lại phương thức thanh toán, gói thuê bao sẽ quay về trạng thái hoạt động và sau đó, bạn phải khôi phục quyền truy cập vào nội dung của gói thuê bao. Trong trường hợp này, mã thông báo giao dịch mua vẫn giống như trước khi quá trình tạm ngưng tài khoản bắt đầu vì chính giao dịch mua đó đang được khôi phục và bạn sẽ nhận được một RTDN thuộc loại SUBSCRIPTION_RECOVERED.

Sau khi khôi phục, Thư viện Play Billing sẽ trả về gói thuê bao một lần nữa thông qua phương thức queryPurchasesAsync(). Nếu bạn dùng phương thức này để xác định xem người dùng có quyền truy cập gói thuê bao hay không, thì ứng dụng của bạn sẽ tự động xử lý quá trình khôi phục gói thuê bao khỏi trạng thái tạm ngưng tài khoản.

Hãy theo dõi thông báo SubscriptionNotification thuộc loại SUBSCRIPTION_RECOVERED để biết khi nào gói thuê bao được khôi phục và người dùng lấy lại quyền truy cập. Nếu bạn truy vấn một gói thuê bao sau khi nhận được thông báo này, thì trường expiryTime sẽ được đặt thành một dấu thời gian trong tương lai, còn trường subscriptionState sẽ lại được đặt thành SUBSCRIPTION_STATE_ACTIVE:

{
  "kind": "androidpublisher#subscriptionPurchaseV2",
  ...
  "subscriptionState": "SUBSCRIPTION_STATE_ACTIVE",
  ...
  "lineItems": [
    {
      "productId": "sub_variant_plan01",
      "expiryTime": next_renewal_date,
      ...
    }
  ],
}

Nếu người dùng không sửa lại phương thức thanh toán trước khi kết thúc thời gian tạm ngưng tài khoản, bạn sẽ nhận được một RTDN thuộc loại SUBSCRIPTION_CANCELED. Để biết hướng dẫn về cách xử lý một yêu cầu huỷ, hãy xem phần Huỷ. Khi bạn truy vấn một gói thuê bao đã bị huỷ theo cách này, trường expiryTime trả về sẽ được đặt thành một dấu thời gian trong quá khứ:

{
  "kind": "androidpublisher#subscriptionPurchaseV2",
  ...
  "subscriptionState": "SUBSCRIPTION_STATE_CANCELED",
  ...
  "lineItems": [
    {
      "productId": "sub_variant_plan01",
      "expiryTime": timestamp_in_past,
      ...
    }
  ],
}

Ngay sau khi nhận được thông báo về việc huỷ trong thời gian tạm ngưng tài khoản, bạn cũng sẽ nhận được một RTDN thuộc loại SUBSCRIPTION_EXPIRED vì người dùng không còn được hưởng quyền của thuê bao trả phí và đã rời bỏ gói thuê bao bằng việc huỷ. Bạn có thể xử lý trường hợp hết hạn này theo cách mà bạn thường làm.

Trong thời gian tạm ngưng tài khoản, người dùng có thể lấy lại quyền truy cập bằng cách mua lại chính gói thuê bao đó hoặc bất kỳ gói nào khác mà bạn cung cấp thông qua ứng dụng từ lần mua ban đầu. Trong trường hợp đó, mã thông báo mới của giao dịch mua sẽ được phát hành và giá trị mới sẽ được trả về như một phần của sự kiện SUBSCRIPTION_PURCHASED đại diện cho thực thể mới này.

Chuyển sang trạng thái tạm ngưng tài khoản và khôi phục

Hình 3 cho biết dòng thời gian của một gói thuê bao chuyển sang trạng thái tạm ngưng tài khoản, sau đó khôi phục khi người dùng sửa lại phương thức thanh toán.

Hình 3. Dòng thời gian của một gói thuê bao chuyển sang trạng thái tạm ngưng tài khoản và khôi phục trước khi thời gian tạm ngưng tài khoản kết thúc.

Tương tự như ví dụ trước, Hình 4 cho thấy dòng thời gian của một gói thuê bao bước vào thời gian ân hạn trước rồi chuyển sang trạng thái tạm ngưng tài khoản, sau đó khôi phục trong thời gian tạm ngưng.

Hình 4. Dòng thời gian của một gói thuê bao bước vào thời gian ân hạn rồi chuyển sang trạng thái tạm ngưng tài khoản, cuối cùng là khôi phục trước khi kết thúc thời gian tạm ngưng tài khoản.

Bạn cần nhớ những điểm sau đây:

  • Trước khi gói thuê bao chuyển sang trạng thái tạm ngưng tài khoản, Google Play sẽ cố gắng tìm cách thu phí bằng phương thức thanh toán này trong tối đa 48 giờ. Trong thời gian này, người dùng vẫn được hưởng các lợi ích của gói thuê bao. Sau khi thời gian thử lại này kết thúc, gói thuê bao sẽ chuyển sang trạng thái tạm ngưng tài khoản và người dùng sẽ mất quyền sử dụng các lợi ích của gói thuê bao.
  • Gói thuê bao sẽ chuyển sang trạng thái tạm ngưng tài khoản ngay khi gói thuê bao tiếp tục hoạt động từ trạng thái tạm dừng do phương thức thanh toán không thành công.
  • Khi gói thuê bao khôi phục sau thời gian tạm ngưng tài khoản, ngày gia hạn sẽ được đặt lại.

Hết hạn

Sau khi gói thuê bao hết hạn, người dùng sẽ mất quyền truy cập vào gói thuê bao đó. Trong trường hợp đó, thông báo SubscriptionNotification thuộc loại SUBSCRIPTION_EXPIRED sẽ được gửi. Khi bạn nhận được thông báo này, hãy truy vấn API Nhà phát triển Google Play để nhận tài nguyên gói thuê bao mới nhất. Sau khi bạn xác nhận rằng subscriptionStateSUBSCRIPTION_STATE_EXPIRED, hãy xoá quyền và đăng ký trạng thái mua hàng là không hợp lệ trong phần phụ trợ. Tài nguyên gói thuê bao sẽ có dạng như trong ví dụ sau:

{
  "kind": "androidpublisher#subscriptionPurchaseV2",
  ...
  "subscriptionState": "SUBSCRIPTION_STATE_EXPIRED",
  ...
  "lineItems": [
    {
      "productId": "sub_variant_plan01",
      "expiryTime": expiration_time_in_past,
      ...
    }
  ],
}

Huỷ

Người dùng có thể tự nguyện huỷ gói thuê bao trong Trung tâm thuê bao của Play hoặc hệ thống sẽ tự động huỷ gói thuê bao nếu họ không khôi phục sau khi bị tạm ngưng tài khoản. Nhà phát triển cũng có thể kích hoạt lệnh huỷ bằng purchases.subscriptions.cancel. Khi gói thuê bao bị huỷ, người dùng vẫn có quyền truy cập vào nội dung cho đến khi kết thúc chu kỳ thanh toán hiện tại. Khi chu kỳ thanh toán kết thúc, quyền truy cập sẽ bị thu hồi.

Việc huỷ gói thuê bao sẽ kích hoạt thông báo SUBSCRIPTION_CANCELED. Khi bạn nhận được thông báo này, tài nguyên gói thuê bao mà hệ thống trả về từ API Nhà phát triển Google Play sẽ có trường subscriptionState được đặt thành SUBSCRIPTION_STATE_CANCELED, còn trường expiryTime chứa ngày mà người dùng sẽ mất quyền truy cập vào gói thuê bao. Nếu ngày đó là ngày trong quá khứ, thì người dùng sẽ mất quyền truy cập ngay lập tức. Điều này có thể xảy ra, chẳng hạn như khi người dùng huỷ một gói thuê bao trong thời gian tạm ngưng tài khoản do bị từ chối thanh toán.

Tài nguyên gói thuê bao của một giao dịch mua bị huỷ sẽ tương tự như ví dụ sau:

{
  "kind": "androidpublisher#subscriptionPurchaseV2",
  ...
  "subscriptionState": "SUBSCRIPTION_STATE_CANCELED",
  ...
  "lineItems": [
    {
      "productId": "sub_variant_plan01",
      "expiryTime": expiration_time,
      ...
    }
  ],
}

Bạn có thể xem trường canceledStateContext trong tài nguyên gói thuê bao để tìm hiểu lý do gói thuê bao huỷ (ví dụ: người dùng, hệ thống hay bạn huỷ gói thuê bao). Nếu người dùng huỷ gói thuê bao, thì bạn có thể xem trường userInitiatedCancellation để tìm hiểu lý do họ làm vậy. Điều này có thể hỗ trợ việc lập chiến lược liên lạc.

Khi một gói thuê bao bị huỷ nhưng chưa hết hạn, queryPurchasesAsync() sẽ vẫn trả về gói thuê bao đó. Bạn có thể muốn hiển thị thông báo trong ứng dụng để người dùng biết gói thuê bao của họ đã bị huỷ và cho họ biết ngày hết hạn.

Thu hồi

Ứng dụng của bạn có thể thu hồi gói thuê bao vì nhiều lý do, trong đó có cả việc thu hồi gói thuê bao bằng cách dùng purchases.subscriptions.revoke hoặc việc hệ thống hoàn trả phí cho giao dịch mua. Trong trường hợp này, hãy thu hồi quyền của người dùng ngay lập tức. Hệ thống sẽ gửi một thông báo SubscriptionNotification thuộc loại SUBSCRIPTION_REVOKED khi trường hợp này xảy ra. Khi bạn nhận được thông báo này, tài nguyên gói thuê bao mà hệ thống trả về từ API Nhà phát triển Google Play sẽ có trường subscriptionState được đặt thành SUBSCRIPTION_STATE_EXPIRED.

Tài nguyên gói thuê bao của một giao dịch mua bị thu hồi sẽ tương tự như ví dụ sau:

{
  "kind": "androidpublisher#subscriptionPurchaseV2",
  ...
  "subscriptionState": "SUBSCRIPTION_STATE_EXPIRED",
  ...
  "lineItems": [
    {
      "productId": "sub_variant_plan01",
      "expiryTime": expiration_time,
      ...
    }
  ]
}

Gói thuê bao bị trì hoãn

Bạn có thể có nhiều lý do để mở rộng quyền của người dùng. Ví dụ: bạn có thể muốn cho phép người dùng truy cập miễn phí dưới dạng một chương trình khuyến mãi đặc biệt, chẳng hạn như tặng một tuần miễn phí để mua phim hoặc cấp quyền truy cập miễn phí cho khách hàng như một hành động thể hiện uy tín kinh doanh. Bạn có thể sử dụng phương thức purchases.subscriptions.defer từ API Nhà phát triển Play để tiến đến ngày thanh toán tiếp theo của một gói thuê bao tự động gia hạn. Khi bạn làm như vậy, một thông báo SubscriptionNotification thuộc loại SUBSCRIPTION_DEFERRED sẽ được gửi. Trong thời gian hoãn, hệ thống sẽ đăng ký cho người dùng đến nội dung của bạn với quyền truy cập đầy đủ nhưng không phải trả phí. Hệ thống sẽ cập nhật ngày gia hạn gói thuê bao tương ứng với ngày mới.

Đối với các gói trả trước, bạn có thể sử dụng API hoãn thanh toán để hoãn thời gian hết hạn.

Tài nguyên gói thuê bao của một gói thuê bao bị trì hoãn sẽ tương tự như ví dụ sau:

{
  "kind": "androidpublisher#subscriptionPurchaseV2",
  ...
  "subscriptionState": "SUBSCRIPTION_STATE_ACTIVE",
  ...
  "lineItems": [
    {
      "productId": "sub_variant_plan01",
      "expiryTime": timestamp_in_future,
      ...
    }
  ],
}

Gói thuê bao bị tạm dừng

Bạn có thể cho phép người dùng tạm dừng gói thuê bao để giảm tình trạng người dùng rời bỏ ứng dụng. Khi bạn bật tính năng tạm dừng, người dùng có thể chọn tạm dừng gói thuê bao của họ trong khoảng thời gian từ 1 tuần đến 3 tháng, tuỳ thuộc vào khoảng thời gian định kỳ.

Việc tạm dừng gói thuê bao chỉ có hiệu lực sau khi kết thúc kỳ thanh toán hiện tại. Trong thời gian gói thuê bao bị tạm dừng, người dùng sẽ không có quyền truy cập vào gói thuê bao và sẽ không trả phí gia hạn. Khi khoảng thời gian tạm dừng kết thúc, gói thuê bao sẽ tiếp tục và Google sẽ cố gắng gia hạn gói thuê bao. Nếu yêu cầu tiếp tục thành công, thì gói thuê bao sẽ hoạt động trở lại. Nếu yêu cầu tiếp tục không thành công do vấn đề thanh toán, người dùng sẽ chuyển sang trạng thái tạm ngưng tài khoản như minh hoạ trong hình 5 và 6:

Hình 5. Một người dùng tạm dừng rồi tiếp tục gói thuê bao.
Hình 6. Một người dùng tạm dừng gói thuê bao, sau đó gói thuê bao chuyển sang trạng thái tạm ngưng tài khoản.

Người dùng cũng có thể chọn tiếp tục gói thuê bao theo cách thủ công bất cứ lúc nào trong khoảng thời gian tạm dừng, như minh hoạ trong hình 6. Khi người dùng tiếp tục theo cách thủ công, ngày thanh toán sẽ thay đổi thành ngày tiếp tục gói thuê bao theo cách thủ công.

Khi người dùng tạm dừng gói thuê bao, Thư viện Play Billing sẽ không trả về gói thuê bao thông qua phương thức queryPurchasesAsync(). Nếu gói thuê bao được tiếp tục, phương thức queryPurchasesAsync() sẽ trả về gói thuê bao đó một lần nữa.

Theo dõi RTDN để biết thời điểm người dùng tạm dừng gói thuê bao. Những thông báo này cũng cho phép bạn thông báo cho người dùng trong ứng dụng của mình rằng họ đã tạm dừng gói thuê bao và không còn quyền truy cập vào gói thuê bao đó. Bạn cũng nên cung cấp cho người dùng một cách để họ có thể tự mình tiếp tục gói thuê bao bất cứ lúc nào bằng đường liên kết sâu đến Google Play.

Hệ thống sẽ gửi một thông báo SubscriptionNotification thuộc loại SUBSCRIPTION_PAUSE_SCHEDULE_CHANGED khi người dùng bắt đầu tạm dừng gói thuê bao. Tại thời điểm này, người dùng vẫn có quyền truy cập vào gói thuê bao cho đến ngày gia hạn tiếp theo và tài nguyên gói thuê bao sẽ chứa autoRenewEnabled = true. Tại thời điểm này, giá trị của trường subscriptionState sẽ là SUBSCRIPTION_STATE_ACTIVE.

Hệ thống sẽ gửi một thông báo SubscriptionNotification thuộc loại SUBSCRIPTION_PAUSED khi yêu cầu tạm dừng có hiệu lực. Khi điều này xảy ra, người dùng sẽ mất quyền truy cập vào gói thuê bao, đồng thời tài nguyên gói thuê bao cũng chứa autoRenewEnabled = true và trường subscriptionState được đặt thành SUBSCRIPTION_STATE_PAUSED. Bạn có thể kiểm tra đối tượng PausedStateContext để xem thời điểm dự kiến mà gói thuê bao sẽ gia hạn một lần nữa.

Hệ thống sẽ gửi một thông báo SubscriptionNotification thuộc loại SUBSCRIPTION_RENEWED nếu gói thuê bao được tiếp tục tự động vào cuối khoảng thời gian tạm dừng hoặc nếu người dùng đã chọn tiếp tục gói thuê bao theo cách thủ công. Bạn nên xử lý vấn đề này theo như mô tả trong phần gia hạn.

Hệ thống sẽ gửi một thông báo SubscriptionNotification thuộc loại SUBSCRIPTION_ON_HOLD nếu có lỗi thanh toán trong khi cố gắng tiếp tục gói thuê bao sau khi tạm dừng. Bạn cần xử lý tình huống này theo cách được mô tả trong phần Tạm ngưng tài khoản.

Đăng ký lại

Đối với các gói cơ bản của gói thuê bao tự động gia hạn, có thể Cửa hàng Google Play sẽ hiện nút Resubscribe (Đăng ký lại). Nút này cho phép người dùng có lại quyền truy cập vào gói thuê bao. Có thể nút này sẽ không xuất hiện vì nhiều lý do, chẳng hạn như gói thuê bao đã hết hạn từ lâu.

Hình 7. Phần Account > Subscriptions (Tài khoản > Gói thuê bao) trong ứng dụng Cửa hàng Google Play cho thấy một gói thuê bao đã bị huỷ có nút Resubscribe (Đăng ký lại).

Mặc dù luôn có nhãn là Đăng ký lại, nhưng chức năng của nút này lại phụ thuộc vào trạng thái của gói thuê bao.

Nếu gói thuê bao đã bị huỷ nhưng chưa hết hạn, thì người dùng vẫn trong trạng thái đăng ký và được hưởng các quyền lợi của gói thuê bao. Nếu người dùng nhấn vào Đăng ký lại, thì trạng thái huỷ sẽ được rút lại thành công và gói thuê bao tiếp tục được gia hạn. Trong các API và tài liệu dành cho nhà phát triển trên Google Play thì thao tác này được gọi là khôi phục.

Sau khi gói thuê bao tự động gia hạn hết hạn, bạn có thể cho phép người dùng mua cùng gói cơ bản trong gói thuê bao đó. Trong các API và tài liệu dành cho nhà phát triển trên Google Play thì thao tác này được gọi là đăng ký lại. Bạn có thể định cấu hình lựa chọn này đối với từng gói cơ bản trong Play Console hoặc sử dụng API.

Khôi phục trước khi hết hạn

Nếu ứng dụng của bạn chỉ dựa vào phương thức queryPurchasesAsync() để xác định xem người dùng có quyền truy cập gói thuê bao hay không, thì ứng dụng sẽ tự động xử lý các yêu cầu khôi phục vì queryPurchasesAsync() sẽ tiếp tục trả về các giao dịch mua đã huỷ trước ngày hết hạn. Một gói thuê bao đã khôi phục sẽ tiếp tục gia hạn như thể chưa bị huỷ.

Nếu ứng dụng của bạn đồng bộ hoá trạng thái gói thuê bao với phần phụ trợ, thì bạn nên theo dõi thông báo SubscriptionNotification thuộc loại SUBSCRIPTION_RESTARTED. Sau khi bạn nhận được RTDN này, ứng dụng của bạn có thể phản hồi thông báo, ghi vào hồ sơ rằng gói thuê bao hiện đã được thiết lập để gia hạn và ngừng hiển thị thông báo khôi phục trong ứng dụng. Tài nguyên gói thuê bao sẽ tương tự như ví dụ sau:

{
  "kind": "androidpublisher#subscriptionPurchaseV2",
  ...
  "subscriptionState": "SUBSCRIPTION_STATE_ACTIVE",
  ...
  "lineItems": [
    {
      "productId": "sub_variant_plan01",
      "expiryTime": next_renewal_date
      ...
    }
  ],
}

Đăng ký lại sau khi hết hạn

Nếu bạn dùng Google Play Console hoặc API để định cấu hình gói cơ bản tự động gia hạn để cho phép Đăng ký lại, thì người dùng có thể mua lại gói thuê bao đã hết hạn trong Cửa hàng Google Play.

Đây là những giao dịch mua mới. Google Play sẽ đưa ra một mã thông báo giao dịch mua hoàn toàn mới, còn hệ thống phụ trợ của bạn nhận được một RTDN thuộc loại SUBSCRIPTION_PURCHASED. Trong trường hợp đó, trạng thái mua hàng của giao dịch mua ngoài ứng dụng thuộc loại này sẽ không chứa linkedPurchaseToken liên kết với giao dịch mua ban đầu, vì gói thuê bao ban đầu đã hết hạn hoàn toàn. Đây là các giao dịch mua mới mà hệ thống phụ trợ của bạn phải xử lý và xác nhận, giống như mọi giao dịch mua khác.

Nâng cấp, hạ cấp và đăng ký lại

Khi người dùng nâng cấp, hạ cấp hoặc đăng ký sau khi huỷ gói thuê bao trong ứng dụng trước khi gói thuê bao hết hạn, thì gói thuê bao cũ sẽ mất hiệu lực và gói thuê bao mới sẽ được tạo bằng mã thông báo mới của giao dịch mua.

Ngoài ra, tài nguyên gói thuê bao đăng ký được trả về từ API Nhà phát triển Google Play sẽ chứa linkedPurchaseToken. Trường này cho biết giao dịch mua cũ mà người dùng đã nâng cấp, hạ cấp hoặc đăng ký lại. Bạn có thể sử dụng mã thông báo giao dịch mua trong trường đó để tra cứu gói thuê bao cũ và xác định tài khoản người dùng hiện có, từ đó có thể liên kết giao dịch mua mới với cùng một tài khoản.

Trước khi cung cấp các lựa chọn nâng cấp, hạ cấp hoặc đăng ký lại trong ứng dụng cho người dùng, bạn phải xác nhận gói thuê bao hiện tại. Nếu gói thuê bao hiện tại vẫn đang ở trạng thái chờ xác nhận, thì mọi thao tác thay đổi hoặc đăng ký lại sẽ bị chặn.

Nếu người dùng thực hiện thành công giao dịch mua nhằm nâng cấp, hạ cấp, hoặc đăng ký lại, thì đây là giao dịch mua mới và bạn phải xác nhận. Bạn nên sử dụng API Nhà phát triển Google Play để thực hiện việc này. Tài nguyên gói thuê bao sẽ có dạng như trong ví dụ sau:

{
  "kind": "androidpublisher#subscriptionPurchaseV2",
  ...
  "subscriptionState": "SUBSCRIPTION_STATE_ACTIVE",
  "linkedPurchaseToken": old_purchase_token,
  ...
  "lineItems": [
    {
      "productId": "sub_variant_plan01",
      "expiryTime": next_renewal_date,
      "autoRenewingPlan": {
        "autoRenewEnabled": true
      }
    }
  ],
}

Thay đổi về giá

Hãy xem hướng dẫn các phương pháp hay nhất về thay đổi giá để tìm hiểu cách thay đổi giá của gói thuê bao tự động gia hạn và thông báo cho người dùng khi thích hợp.

Khi những thay đổi về giá được áp dụng ở dạng chọn đồng ý đối với người dùng hiện có, bạn sẽ nhận được thông báo RTDN nếu người dùng đưa ra hành động để xác nhận hoặc từ chối giá mới.

Xử lý xác nhận của người dùng về việc chọn đồng ý với thay đổi về giá

Nếu người dùng chấp nhận mức tăng giá của gói thuê bao, thì bạn sẽ nhận được thông báo SubscriptionNotification thuộc loại SUBSCRIPTION_PRICE_CHANGED_CONFIRMED. Với mức giảm giá ở chế độ người dùng chọn không đồng ý hoặc khi gia hạn tăng giá gói thuê bao, bạn sẽ nhận được thông báo SubscriptionNotification thuộc loại SUBSCRIPTION_RENEWED. Hãy xử lý thông báo này giống như mọi trường hợp gia hạn khác.

Xử lý trường hợp người dùng không chấp nhận việc tăng giá

Nếu người dùng chưa chấp nhận việc tăng giá trước khi cần gia hạn theo mức giá cao hơn, thì họ sẽ tự động bị huỷ đăng ký và bạn sẽ nhận được thông báo SubscriptionNotification thuộc loại SUBSCRIPTION_CANCELED. Hãy xử lý sự kiện này như mô tả trong phần Huỷ.

Theo cơ chế tương tự, người dùng cũng có thể huỷ gói thuê bao đối với việc tăng giá cần người dùng đồng ý.

Xử lý vòng đời của gói trả trước

Giống như gói thuê bao tự động gia hạn, bạn phải xác nhận các gói trả trước sau mỗi giao dịch mua mới. Đối với gói trả trước, bạn phải xử lý đầy đủ cả giao dịch mua ban đầu và mọi giao dịch nạp tiền, vì mỗi lần người dùng đều phải trải qua quy trình mua hàng.

Do thời hạn gói trả trước có thể ngắn, điều quan trọng là bạn phải xác nhận giao dịch mua càng sớm càng tốt. Gói trả trước có thời hạn một tuần trở lên phải được xác nhận trong vòng 3 ngày. Bạn phải xác nhận các gói trả trước có thời hạn ngắn hơn một tuần trong vòng một nửa thời lượng của gói. Ví dụ: nhà phát triển có 1,5 ngày để xác nhận giao dịch mua gói trả trước 3 ngày.

Hình 8. Các trạng thái vòng đời và sự kiện chuyển đổi của giao dịch mua gói thuê bao.

Thông báo SubscriptionNotification thuộc loại SUBSCRIPTION_PURCHASED sẽ được gửi tới máy khách RTDN của bạn mỗi khi người dùng mua gói thuê bao trả trước, bao gồm cả mỗi lần nạp tiền. Hãy gọi phương thức purchases.subscriptionsv2.get để kiểm tra trạng thái mới nhất của gói thuê bao trả trước.

Mã thông báo mới của giao dịch mua sẽ được phát hành cho các giao dịch nạp tiền và bạn sẽ nhận được mã thông báo giao dịch mua trước đó trong trường linkedPurchaseToken trong trạng thái giao dịch mua gói thuê bao mới.

Tài nguyên gói thuê bao của giao dịch mua gói thuê bao trả trước sẽ tương tự như trong ví dụ sau:

{
  "kind": "androidpublisher#subscriptionPurchaseV2",
  "startTime": "2022-04-22T18:39:58.270Z",
  "regionCode": "US",
  "subscriptionState": "SUBSCRIPTION_STATE_ACTIVE",
  "latestOrderId": "GPA.3333-4137-0319-36762",
  "acknowledgementState": "ACKNOWLEDGEMENT_STATE_ACKNOWLEDGED",
  "lineItems": [
    {
      "productId": "prepaid_plan01",
      "expiryTime": expiry_date,
      "prepaidPlan": {
        "allowExtendAfterTime": timestamp_after_which_topups_are_allowed
      }
    }
  ]
}

Bạn có thể xem thời điểm quyền kết thúc trong trường expiryTime. Các giao dịch nạp tiền sẽ tích luỹ và tăng thời gian được hưởng quyền. Điều đó có nghĩa là nếu người dùng nạp tiền trước khi quyền ban đầu của họ kết thúc, thì thời gian mới sẽ được thêm vào ngày hết hạn trước đó của họ.

Bạn có thể muốn hiển thị thông báo trong ứng dụng để thông báo cho người dùng rằng gói thuê bao trả trước của họ có thể được gia hạn bằng cách nạp tiền. Để biết thời điểm người dùng có thể nạp tiền, hãy kiểm tra trường allowExtendAfterTime trong tài nguyên gói thuê bao.

Gói trả trước không tự động gia hạn nên sẽ không huỷ được. Nếu muốn huỷ gói trả trước, người dùng có thể để gói thuê bao hết hạn.