Flutter - Xử lý sự kiện paywall
Hướng dẫn này đề cập đến việc xử lý sự kiện cho các giao dịch mua, khôi phục, chọn sản phẩm và hiển thị paywall. Bạn cũng cần triển khai xử lý nút bấm (đóng paywall, mở liên kết, v.v.). Xem hướng dẫn xử lý hành động nút bấm để biết thêm chi tiết.
Các paywall được cấu hình bằng Paywall Builder không cần thêm code để thực hiện và khôi phục giao dịch mua. Tuy nhiên, chúng tạo ra một số sự kiện mà ứng dụng của bạn có thể phản hồi. Các sự kiện đó bao gồm thao tác nhấn nút (nút đóng, URL, chọn sản phẩm, v.v.) cũng như thông báo về các hành động liên quan đến giao dịch mua trên paywall. Tìm hiểu cách phản hồi các sự kiện này bên dưới.
Hướng dẫn này chỉ dành cho paywall Paywall Builder mới yêu cầu Adapty SDK v3.0 trở lên.
Để kiểm soát hoặc theo dõi các tiến trình diễn ra trên màn hình paywall trong ứng dụng di động của bạn, hãy triển khai các phương thức AdaptyUIPaywallsEventsObserver và thiết lập observer trước khi hiển thị bất kỳ màn hình nào:
AdaptyUI().setPaywallsEventsObserver(this);
Muốn xem ví dụ thực tế về cách tích hợp Adapty SDK vào ứng dụng di động? Hãy xem ứng dụng mẫu của chúng tôi, nơi minh họa toàn bộ quá trình thiết lập, bao gồm hiển thị paywall, thực hiện mua hàng và các chức năng cơ bản khác.
Sự kiện do người dùng tạo ra
Paywall xuất hiện
Phương thức này được gọi khi màn hình paywall được hiển thị trên màn hình.
Trên iOS, cũng được gọi khi người dùng nhấn vào nút web paywall bên trong paywall và một web paywall mở ra trong trình duyệt trong ứng dụng.
void paywallViewDidAppear(AdaptyUIPaywallView view) {
}
Paywall biến mất
Phương thức này được gọi khi màn hình paywall bị đóng khỏi màn hình.
Trên iOS, cũng được gọi khi một web paywall được mở từ paywall trong trình duyệt trong ứng dụng biến mất khỏi màn hình.
void paywallViewDidDisappear(AdaptyUIPaywallView view) {
}
Chọn sản phẩm
Nếu một sản phẩm được chọn để mua (bởi người dùng hoặc hệ thống), phương thức này sẽ được gọi:
void paywallViewDidSelectProduct(AdaptyUIPaywallView view, String productId) {
}
Ví dụ sự kiện (Nhấn để mở rộng)
{
"productId": "premium_monthly"
}Bắt đầu mua
Nếu người dùng khởi tạo quá trình mua, phương thức này sẽ được gọi:
void paywallViewDidStartPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product) {
}
Ví dụ sự kiện (Nhấn để mở rộng)
{
"product": {
"vendorProductId": "premium_monthly",
"localizedTitle": "Premium Monthly",
"localizedDescription": "Premium subscription for 1 month",
"localizedPrice": "$9.99",
"price": 9.99,
"currencyCode": "USD"
}
}Hoàn thành mua
Phương thức này được gọi khi giao dịch mua thành công, người dùng hủy giao dịch mua, hoặc giao dịch mua đang ở trạng thái chờ xử lý:
void paywallViewDidFinishPurchase(AdaptyUIPaywallView view,
AdaptyPaywallProduct product,
AdaptyPurchaseResult purchaseResult) {
switch (purchaseResult) {
case AdaptyPurchaseResultSuccess(profile: final profile):
// successful purchase
break;
case AdaptyPurchaseResultPending():
// purchase is pending
break;
case AdaptyPurchaseResultUserCancelled():
// user cancelled the purchase
break;
default:
break;
}
}
Ví dụ sự kiện (Nhấn để mở rộng)
// Successful purchase
{
"product": {
"vendorProductId": "premium_monthly",
"localizedTitle": "Premium Monthly",
"localizedDescription": "Premium subscription for 1 month",
"localizedPrice": "$9.99",
"price": 9.99,
"currencyCode": "USD"
},
"purchaseResult": {
"type": "AdaptyPurchaseResultSuccess",
"profile": {
"accessLevels": {
"premium": {
"id": "premium",
"isActive": true,
"expiresAt": "2024-02-15T10:30:00Z"
}
}
}
}
}
// Pending purchase
{
"product": {
"vendorProductId": "premium_monthly",
"localizedTitle": "Premium Monthly",
"localizedDescription": "Premium subscription for 1 month",
"localizedPrice": "$9.99",
"price": 9.99,
"currencyCode": "USD"
},
"purchaseResult": {
"type": "AdaptyPurchaseResultPending"
}
}
// User cancelled purchase
{
"product": {
"vendorProductId": "premium_monthly",
"localizedTitle": "Premium Monthly",
"localizedDescription": "Premium subscription for 1 month",
"localizedPrice": "$9.99",
"price": 9.99,
"currencyCode": "USD"
},
"purchaseResult": {
"type": "AdaptyPurchaseResultUserCancelled"
}
}Chúng tôi khuyến nghị đóng màn hình trong trường hợp đó. Tham khảo Phản hồi hành động nút bấm để biết chi tiết về cách đóng màn hình paywall.
Hoàn thành điều hướng thanh toán web
Phương thức này được gọi sau khi thử mở một web paywall cho một sản phẩm cụ thể. Điều này bao gồm cả các lần điều hướng thành công và thất bại:
void paywallViewDidFinishWebPaymentNavigation(AdaptyUIPaywallView view,
AdaptyPaywallProduct? product,
AdaptyError? error) {
}
Tham số:
| Tham số | Mô tả |
|---|---|
| product | Một AdaptyPaywallProduct mà web paywall được mở cho. Có thể là null. |
| error | Một đối tượng AdaptyError nếu điều hướng web paywall thất bại; null nếu điều hướng thành công. |
Ví dụ sự kiện (Nhấn để mở rộng)
// Successful navigation
{
"product": {
"vendorProductId": "premium_monthly",
"localizedTitle": "Premium Monthly",
"localizedDescription": "Premium subscription for 1 month",
"localizedPrice": "$9.99",
"price": 9.99,
"currencyCode": "USD"
},
"error": null
}
// Failed navigation
{
"product": {
"vendorProductId": "premium_monthly",
"localizedTitle": "Premium Monthly",
"localizedDescription": "Premium subscription for 1 month",
"localizedPrice": "$9.99",
"price": 9.99,
"currencyCode": "USD"
},
"error": {
"code": "web_navigation_failed",
"message": "Failed to open web paywall",
"details": {
"underlyingError": "Browser unavailable"
}
}
}Mua thất bại
Phương thức này được gọi khi giao dịch mua thất bại (ví dụ: do lỗi thanh toán hoặc lỗi mạng). Phương thức này không kích hoạt khi người dùng chủ động hủy hoặc giao dịch đang chờ xử lý — những trường hợp đó được xử lý bởi paywallViewDidFinishPurchase:
void paywallViewDidFailPurchase(AdaptyUIPaywallView view,
AdaptyPaywallProduct product,
AdaptyError error) {
}
Ví dụ sự kiện (Nhấn để mở rộng)
{
"product": {
"vendorProductId": "premium_monthly",
"localizedTitle": "Premium Monthly",
"localizedDescription": "Premium subscription for 1 month",
"localizedPrice": "$9.99",
"price": 9.99,
"currencyCode": "USD"
},
"error": {
"code": "purchase_failed",
"message": "Purchase failed due to insufficient funds",
"details": {
"underlyingError": "Insufficient funds in account"
}
}
}Bắt đầu khôi phục
Nếu người dùng khởi tạo quá trình khôi phục, phương thức này sẽ được gọi:
void paywallViewDidStartRestore(AdaptyUIPaywallView view) {
}
Khôi phục thành công
Nếu khôi phục giao dịch mua thành công, phương thức này sẽ được gọi:
void paywallViewDidFinishRestore(AdaptyUIPaywallView view, AdaptyProfile profile) {
}
Ví dụ sự kiện (Nhấn để mở rộng)
{
"profile": {
"accessLevels": {
"premium": {
"id": "premium",
"isActive": true,
"expiresAt": "2024-02-15T10:30:00Z"
}
},
"subscriptions": [
{
"vendorProductId": "premium_monthly",
"isActive": true,
"expiresAt": "2024-02-15T10:30:00Z"
}
]
}
}Chúng tôi khuyến nghị đóng màn hình nếu người dùng có accessLevel yêu cầu. Tham khảo chủ đề Trạng thái gói đăng ký để tìm hiểu cách kiểm tra và chủ đề Phản hồi hành động nút bấm để tìm hiểu cách đóng màn hình paywall.
Khôi phục thất bại
Nếu khôi phục giao dịch mua thất bại, phương thức này sẽ được gọi:
void paywallViewDidFailRestore(AdaptyUIPaywallView view, AdaptyError error) {
}
Ví dụ sự kiện (Nhấn để mở rộng)
{
"error": {
"code": "restore_failed",
"message": "Purchase restoration failed",
"details": {
"underlyingError": "No previous purchases found"
}
}
}Tải dữ liệu và hiển thị
Lỗi tải sản phẩm
Nếu bạn không truyền mảng sản phẩm trong quá trình khởi tạo, AdaptyUI sẽ tự động lấy các đối tượng cần thiết từ máy chủ. Nếu thao tác này thất bại, AdaptyUI sẽ báo lỗi bằng cách gọi phương thức này:
void paywallViewDidFailLoadingProducts(AdaptyUIPaywallView view, AdaptyError error) {
}
Ví dụ sự kiện (Nhấn để mở rộng)
{
"error": {
"code": "products_loading_failed",
"message": "Failed to load products from the server",
"details": {
"underlyingError": "Network timeout"
}
}
}Lỗi hiển thị
Nếu xảy ra lỗi trong quá trình hiển thị giao diện, lỗi đó sẽ được báo cáo bằng cách gọi phương thức này. Theo mặc định (kể từ v3.15.2), paywall sẽ tự động bị đóng khi xảy ra lỗi hiển thị, nhưng bạn có thể ghi đè hành vi này nếu cần.
void paywallViewDidFailRendering(AdaptyUIPaywallView view, AdaptyError error) {
// Default behavior: view.dismiss()
// Override with custom logic if needed, for example:
// - Log the error
// - Show an error message to the user
}
Ví dụ sự kiện (Nhấn để mở rộng)
{
"error": {
"code": "rendering_failed",
"message": "Failed to render paywall interface",
"details": {
"underlyingError": "Invalid paywall configuration"
}
}
}Trong điều kiện bình thường, các lỗi như vậy không nên xảy ra, vì vậy nếu bạn gặp phải, hãy cho chúng tôi biết.