Luồng sự kiện
Một hành động thường tạo ra nhiều sự kiện. Ví dụ, một lần mua đầu tiên sẽ gửi cả Subscription started lẫn Access level updated. Các sơ đồ dưới đây cho thấy những gì Adapty gửi khi khách hàng đăng ký, hủy, hoặc kích hoạt lại, và theo thứ tự nào.
Cách đọc các sơ đồ
- Thời điểm. Apple tính phí cho một gói đăng ký trước khi bắt đầu hoặc gia hạn vài giờ. Hiển thị khoảng cách đó sẽ thêm một bước vào mỗi sơ đồ mà không thay đổi sự kiện bạn nhận được, vì vậy các sơ đồ đặt lần tính phí và lần bắt đầu cùng nhau.
- Thứ tự. Các sự kiện từ một hành động đến cùng một lúc. Sơ đồ phải vẽ chúng theo một thứ tự nào đó, nhưng Event Feed của bạn có thể liệt kê chúng theo thứ tự khác, và cả hai đều không sai.
- Phạm vi. Một thông báo từ cửa hàng kích hoạt mọi sự kiện được hiển thị. Synthetic events không xuất hiện: Adapty gửi chúng theo bộ hẹn giờ, và độ trễ khác nhau theo từng tích hợp, nên chúng không có vị trí cố định trong một chuỗi.
Vòng đời gói đăng ký
Luồng mua lần đầu
Luồng này xảy ra khi khách hàng mua gói đăng ký lần đầu tiên mà không có dùng thử. Trong trường hợp này, các sự kiện sau được tạo ra:
- Subscription started
- Access level updated để cấp quyền truy cập cho người dùng
Khi đến ngày gia hạn gói đăng ký, gói đăng ký sẽ được gia hạn. Trong trường hợp này, các sự kiện sau được tạo ra:
- Subscription renewal để bắt đầu một kỳ mới của gói đăng ký
- Access level updated để cập nhật ngày hết hạn gói đăng ký, kéo dài quyền truy cập thêm một kỳ nữa
Các tình huống khi thanh toán không thành công hoặc khi người dùng hủy gia hạn được mô tả trong Billing Issue Outcome Flow và Subscription Cancellation Flow, tương ứng.
Luồng Hủy Gói Đăng Ký
Khi người dùng hủy gói đăng ký, các sự kiện sau sẽ được tạo ra:
- Subscription renewal canceled để cho biết rằng gói đăng ký vẫn còn hiệu lực đến hết kỳ hiện tại, sau đó người dùng sẽ mất quyền truy cập
- Sự kiện Access level updated được tạo ra để tắt tính năng tự động gia hạn cho mức độ truy cập
Khi gói đăng ký kết thúc, sự kiện Subscription expired (churned) được kích hoạt để đánh dấu kết thúc gói đăng ký.
Nếu yêu cầu hoàn tiền được chấp thuận, sự kiện sau sẽ thay thế Subscription expired (churned):
- Subscription refunded để kết thúc gói đăng ký và cung cấp thông tin chi tiết về khoản hoàn tiền
Đối với Stripe, gói đăng ký có thể bị hủy ngay lập tức, bỏ qua thời gian còn lại. Trong trường hợp này, tất cả các sự kiện được tạo đồng thời:
- Subscription renewal cancelled
- Subscription expired (churned)
- Access Level updated để xóa quyền truy cập của người dùng
Nếu yêu cầu hoàn tiền được chấp thuận, sự kiện Subscription refunded cũng sẽ được kích hoạt khi yêu cầu đó được duyệt.
Luồng kích hoạt lại gói đăng ký
Nếu người dùng hủy gói đăng ký, gói đó hết hạn và sau đó họ mua lại cùng gói đăng ký đó, sự kiện Subscription renewed sẽ được tạo ra. Ngay cả khi có khoảng thời gian gián đoạn quyền truy cập, Adapty xử lý đây là một chuỗi giao dịch duy nhất, được liên kết bởi vendor_original_transaction_id. Vì vậy, việc mua lại được coi là một lần gia hạn.
Các sự kiện Access level updated sẽ được tạo ra hai lần:
- vào lúc kết thúc gói đăng ký để thu hồi quyền truy cập của người dùng
- vào lúc mua lại gói đăng ký để cấp quyền truy cập
Luồng tạm dừng gói đăng ký (chỉ Android)
Luồng này áp dụng khi người dùng tạm dừng và sau đó tiếp tục gói đăng ký trên Android.
Việc tạm dừng gói đăng ký có hiệu lực trì hoãn. Nếu người dùng tạm dừng gói đăng ký trước khi đến ngày gia hạn, gói đăng ký vẫn còn hiệu lực và người dùng vẫn được truy cập trong phần còn lại của kỳ thanh toán.
-
Khi người dùng tạm dừng gói đăng ký, họ kích hoạt sự kiện Subscription paused (Android only).
-
Vào cuối kỳ gói đăng ký, Adapty kích hoạt sự kiện Access level updated để thu hồi quyền truy cập của người dùng.
-
Khi người dùng tiếp tục gói đăng ký, các sự kiện sau được kích hoạt:
- Subscription renewed
- Access level updated để khôi phục quyền truy cập của người dùng
Các gói đăng ký này sẽ thuộc cùng một chuỗi giao dịch, được liên kết với cùng vendor_original_transaction_id.
Luồng dùng thử
Nếu bạn sử dụng tính năng dùng thử trong ứng dụng, bạn sẽ nhận được các sự kiện bổ sung liên quan đến dùng thử.
Flow Dùng Thử Với Chuyển Đổi Thành Công
Flow phổ biến nhất xảy ra khi người dùng bắt đầu dùng thử, cung cấp thẻ tín dụng và chuyển đổi thành công sang gói đăng ký tiêu chuẩn vào cuối giai đoạn dùng thử. Trong tình huống này, các sự kiện sau được tạo ra tại thời điểm bắt đầu dùng thử:
- Trial started để đánh dấu thời điểm bắt đầu dùng thử
- Access level updated để cấp quyền truy cập
Sự kiện Trial converted được tạo ra khi gói đăng ký tiêu chuẩn bắt đầu.
Luồng dùng thử không chuyển đổi thành công
Nếu người dùng hủy dùng thử trước khi chuyển đổi thành gói đăng ký, các sự kiện sau sẽ được tạo vào thời điểm hủy:
- Trial renewal cancelled để vô hiệu hóa tính năng tự động chuyển đổi dùng thử thành gói đăng ký
- Access level updated để vô hiệu hóa việc gia hạn mức độ truy cập
Người dùng vẫn có quyền truy cập cho đến khi hết thời gian dùng thử, khi đó sự kiện Trial expired sẽ được tạo để đánh dấu kết thúc dùng thử.
Luồng kích hoạt lại gói đăng ký sau khi dùng thử hết hạn
Nếu dùng thử hết hạn (do sự cố thanh toán hoặc hủy) và người dùng sau đó mua gói đăng ký, các sự kiện sau được tạo ra:
- Access level updated để cấp quyền truy cập cho người dùng
- Trial converted
Ngay cả khi có khoảng thời gian gián đoạn giữa dùng thử và gói đăng ký, Adapty liên kết hai sự kiện này bằng vendor_original_transaction_id. Việc chuyển đổi này được coi là một phần của chuỗi giao dịch liên tục, bắt đầu bằng dùng thử miễn phí. Đó là lý do tại sao sự kiện Trial converted được tạo ra thay vì Subscription started.
Thay đổi sản phẩm
Phần này đề cập đến mọi điều chỉnh đối với gói đăng ký đang hoạt động, chẳng hạn như nâng cấp, hạ cấp hoặc mua sản phẩm từ nhóm khác.
Luồng thay đổi sản phẩm ngay lập tức
Sau khi người dùng thay đổi sản phẩm, nó có thể được thay đổi trong hệ thống ngay lập tức trước khi gói đăng ký kết thúc (chủ yếu trong trường hợp nâng cấp hoặc thay thế sản phẩm). Trong trường hợp này, tại thời điểm thay đổi sản phẩm:
- Mức độ truy cập được thay đổi và hai sự kiện Access level updated được tạo ra:
- để xóa quyền truy cập vào sản phẩm đầu tiên.
- để cấp quyền truy cập vào sản phẩm thứ hai.
- Gói đăng ký cũ kết thúc và hoàn tiền được thực hiện (sự kiện Subscription refunded được tạo ra với
cancellation_reason=upgraded). Lưu ý rằng không có sự kiện Subscription expired (churned) nào được tạo ra; sự kiện Subscription refunded thay thế nó. - Gói đăng ký mới bắt đầu (sự kiện Subscription started được tạo ra cho sản phẩm mới).
Nếu người dùng hạ cấp gói đăng ký, gói đăng ký đầu tiên sẽ có hiệu lực đến hết chu kỳ thanh toán đã trả, và khi gói đăng ký kết thúc, nó sẽ được thay thế bằng gói đăng ký cấp thấp hơn. Trong trường hợp này, chỉ có sự kiện Access level updated để tắt tự gia hạn quyền truy cập được tạo ngay lập tức. Tất cả các sự kiện khác sẽ được tạo vào thời điểm gói đăng ký thực sự được thay thế:
- Một sự kiện Access level updated khác được tạo ra để cấp quyền truy cập cho sản phẩm thứ hai.
- Sự kiện Subscription expired (churned) được tạo ra để kết thúc gói đăng ký của sản phẩm đầu tiên.
- Sự kiện Subscription started được tạo ra để bắt đầu gói đăng ký mới cho sản phẩm mới.
Luồng thay đổi sản phẩm trì hoãn
Cũng có một biến thể khi người dùng thay đổi sản phẩm vào thời điểm gia hạn gói đăng ký. Biến thể này rất giống với biến thể trước: một sự kiện Access level updated sẽ được tạo ra ngay lập tức để tắt tự động gia hạn quyền truy cập cho sản phẩm cũ. Tất cả các sự kiện khác sẽ được tạo ra tại thời điểm người dùng thay đổi gói đăng ký và nó được thay đổi trong hệ thống:
- Một sự kiện Access level updated khác được tạo ra để cấp quyền truy cập cho sản phẩm thứ hai.
- Sự kiện Subscription expired (churned) được tạo ra để kết thúc gói đăng ký cho sản phẩm đầu tiên.
- Sự kiện Subscription started được tạo ra để bắt đầu một gói đăng ký mới cho sản phẩm mới.
Luồng kết quả sự cố thanh toán
Nếu các lần thử chuyển đổi dùng thử hoặc gia hạn gói đăng ký thất bại do sự cố thanh toán, những gì xảy ra tiếp theo phụ thuộc vào việc thời gian ân hạn có được bật hay không.
Với thời gian ân hạn, nếu thanh toán thành công, dùng thử sẽ được chuyển đổi hoặc gói đăng ký được gia hạn. Nếu thất bại, cửa hàng ứng dụng sẽ tiếp tục cố gắng tính phí người dùng cho gói đăng ký và nếu vẫn thất bại, cửa hàng ứng dụng sẽ tự kết thúc dùng thử hoặc gói đăng ký.
Do đó, tại thời điểm xảy ra sự cố thanh toán, các sự kiện sau được tạo ra trong Adapty:
- Billing issue detected
- Entered grace period (nếu thời gian ân hạn được bật)
- Access level updated để cấp quyền truy cập đến cuối thời gian ân hạn
Nếu thanh toán thành công sau đó, Adapty ghi lại sự kiện Trial converted hoặc Subscription renewed, và người dùng không mất quyền truy cập.
Nếu thanh toán cuối cùng thất bại và cửa hàng ứng dụng hủy gói đăng ký, Adapty tạo ra các sự kiện sau:
- Trial expired hoặc Subscription expired (churned) với
cancellation_reason: billing_error - Access level updated để thu hồi quyền truy cập của người dùng
Nếu không có thời gian ân hạn, Thời gian Thử lại Thanh toán (khoảng thời gian cửa hàng tiếp tục cố gắng tính phí người dùng) sẽ bắt đầu ngay lập tức.
Nếu thanh toán không thành công cho đến hết thời gian ân hạn, flow vẫn diễn ra tương tự: các sự kiện tương tự sẽ được tạo ra khi cửa hàng tự động kết thúc gói đăng ký:
-
Sự kiện Trial expired hoặc Subscription expired (churned) với
cancellation_reasonlàbilling_error -
Access level updated để thu hồi quyền truy cập của người dùng
Luồng chia sẻ giao dịch mua giữa các tài khoản người dùng
Khi một Customer User ID iOS, Android, React Native, Flutter, và Unity cố gắng khôi phục hoặc mở rộng gói đăng ký đã được liên kết với một Customer User ID iOS, Android, React Native, Flutter, và Unity khác, cài đặt Sharing paid access between user accounts của Adapty sẽ kiểm soát cách quản lý quyền truy cập. Luồng sẽ thay đổi tùy thuộc vào tùy chọn được chọn.
Đối với các giao dịch Apple Family Sharing (in_app_ownership_type=FAMILY_SHARED), chỉ có sự kiện Access level updated được kích hoạt — các sự kiện gói đăng ký theo từng sản phẩm bên dưới sẽ không được kích hoạt. Xem Apple Family Sharing để biết ma trận sự kiện đầy đủ.
Nếu người dùng nhấn Restore Purchases nhưng đã có quyền truy cập trên cùng hồ sơ người dùng, thao tác khôi phục không có tác dụng và không có sự kiện webhook nào được kích hoạt. Các sự kiện trong phần này chỉ được kích hoạt khi quyền truy cập thực sự được chuyển giữa các hồ sơ.
Để xem nhanh các sự kiện nào được kích hoạt khi hồ sơ thứ hai yêu cầu một gói đăng ký hiện có, hãy sử dụng ma trận này. Các phần tiếp theo hiển thị toàn bộ JSON payload cho mỗi luồng.
| Sự kiện | Enabled (mặc định) | Transfer access to new user | Disabled |
|---|---|---|---|
Hồ sơ mới: Access level updated (is_active=true) | Được kích hoạt | Được kích hoạt | Không được kích hoạt |
Hồ sơ cũ: Access level updated (is_active=false) | Không được kích hoạt — cả hai hồ sơ đều giữ quyền truy cập | Được kích hoạt khi thiết bị mới được nhận dạng truyền giao dịch | Không được kích hoạt — hồ sơ gốc giữ quyền truy cập |
Trường profiles_sharing_access_level trong sự kiện mới | Liệt kê các hồ sơ khác chia sẻ mức độ truy cập | null | Không áp dụng — không có sự kiện nào được kích hoạt |
Các lần gia hạn, hoàn tiền và hết hạn trên gói đăng ký đã được chuyển tiếp tục kích hoạt các sự kiện subscription_renewed, subscription_refunded và subscription_expired trên hồ sơ hiện đang nắm giữ mức độ truy cập. Sự kiện chuyển nhượng bản thân không phát ra sự kiện subscription_started, vì không có giao dịch mới nào được ghi lại — chỉ có attribution thay đổi.
Để biết chi tiết hợp đồng theo từng chế độ, xem Tài liệu tham khảo thực tế.
Chuyển quyền truy cập sang luồng người dùng mới
Lựa chọn được khuyến nghị là chuyển mức độ truy cập sang người dùng mới. Cách này giữ nguyên lịch sử giao dịch của người dùng gốc để đảm bảo tính nhất quán trong phân tích. Chỉ có 2 sự kiện Access level updated được tạo ra:
- để xóa quyền truy cập của người dùng đầu tiên
- để cấp quyền truy cập cho người dùng thứ hai
Dưới đây là phân tích các trường liên quan đến việc gán và chuyển mức độ truy cập trong các sự kiện được tạo ra trong kịch bản này:
-
User A: Mức độ truy cập được cập nhật (gửi khi User A mua gói đăng ký trong ứng dụng)
{ "profile_id": "00000000-0000-0000-0000-000000000000", "customer_user_id": UserA, "event_properties": { "profile_has_access_level": true, }, "profiles_sharing_access_level": null } -
User A: Mức độ truy cập được cập nhật (gửi khi ứng dụng được cài đặt lại và User B đăng nhập, thu hồi quyền truy cập của User A)
{ "profile_id": "00000000-0000-0000-0000-000000000000", "customer_user_id": UserA, "event_properties": { "profile_has_access_level": false, }, "profiles_sharing_access_level": null } -
User B: Access level updated (được gửi khi User B đăng nhập và quyền truy cập được cấp)
{ "profile_id": "00000000-0000-0000-0000-000000000001", "customer_user_id": UserB, "event_properties": { "profile_has_access_level": true, }, "profiles_sharing_access_level": null }
Luồng chia sẻ quyền truy cập giữa các người dùng
Tùy chọn này cho phép nhiều người dùng chia sẻ cùng mức độ truy cập nếu thiết bị của họ được đăng nhập vào cùng Apple/Google ID. Điều này hữu ích khi người dùng cài đặt lại ứng dụng và đăng nhập bằng email khác — họ vẫn sẽ có quyền truy cập vào giao dịch mua trước đó. Với tùy chọn này, nhiều người dùng được xác định có thể chia sẻ cùng mức độ truy cập. Trong khi mức độ truy cập được chia sẻ, tất cả các giao dịch được ghi lại dưới Customer User ID iOS, Android, React Native, Flutter, và Unity gốc để duy trì lịch sử giao dịch và phân tích đầy đủ.
Do đó, chỉ có 1 sự kiện được tạo ra: Access level updated để cấp quyền truy cập cho người dùng thứ hai.
Dưới đây là chi tiết các trường liên quan đến việc gán và chia sẻ mức độ truy cập trong các sự kiện được tạo ra trong kịch bản này:
User B: Access level updated (được gửi khi User B đăng nhập và quyền truy cập được cấp)
{
"profile_id": "00000000-0000-0000-0000-000000000000",
"customer_user_id": UserA,
"event_properties": {
"profile_has_access_level": true,
},
"profiles_sharing_access_level": [
{
"profile_id": "00000000-0000-0000-0000-000000000001,
"customer_user_id": UserB
}
]
}
Luồng không chia sẻ quyền truy cập giữa các người dùng
Với tùy chọn này, chỉ hồ sơ người dùng đầu tiên nhận được mức độ truy cập mới giữ nó vĩnh viễn. Điều này lý tưởng khi các giao dịch mua cần được gắn với một Customer User ID iOS, Android, React Native, Flutter, và Unity duy nhất.