Flutter - 处理付费墙事件

本指南涵盖购买、恢复购买、产品选择及付费墙渲染的事件处理。您还必须实现按钮处理(关闭付费墙、打开链接等)。详情请参阅我们的按钮操作处理指南

使用付费墙编辑工具配置的付费墙无需额外代码即可完成购买和恢复购买。但它们会生成一些您的应用可以响应的事件。这些事件包括按钮按下(关闭按钮、URL、产品选择等)以及付费墙上购买相关操作的通知。请阅读以下内容了解如何响应这些事件。

本指南仅适用于新版付费墙编辑工具付费墙,需要 Adapty SDK v3.0 或更高版本。如需了解在 Adapty SDK v2 中展示使用旧版付费墙编辑工具设计的付费墙,请参阅 Flutter - 处理使用旧版付费墙编辑工具设计的付费墙事件

要控制或监控移动应用中付费墙屏幕上发生的流程,请实现 AdaptyUIPaywallsEventsObserver 方法,并在展示任何屏幕之前设置观察者:

AdaptyUI().setPaywallsEventsObserver(this);

想了解 Adapty SDK 如何集成到移动应用中的真实示例?请查看我们的示例应用,其中展示了完整的配置过程,包括显示付费墙、完成购买以及其他基本功能。

用户生成的事件

付费墙出现

当付费墙视图在屏幕上展示时,将调用此方法。

在 iOS 上,当用户点击付费墙内的网页付费墙按钮,且网页付费墙在应用内浏览器中打开时,也会调用此方法。

void paywallViewDidAppear(AdaptyUIPaywallView view) {
}

付费墙消失

当付费墙视图从屏幕上消失时,将调用此方法。

在 iOS 上,当从付费墙中在应用内浏览器打开的网页付费墙从屏幕上消失时,也会调用此方法。

void paywallViewDidDisappear(AdaptyUIPaywallView view) {
}

产品选择

如果用户或系统选择了某个产品进行购买,将调用此方法:

void paywallViewDidSelectProduct(AdaptyUIPaywallView view, String productId) {
}
事件示例(点击展开)
{
  "productId": "premium_monthly"
}

开始购买

如果用户发起购买流程,将调用此方法:

void paywallViewDidStartPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product) {
}
事件示例(点击展开)
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  }
}

完成购买

当购买成功、用户取消购买或购买处于待处理状态时,将调用此方法:

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;
    }
}
事件示例(点击展开)
// 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"
  }
}

我们建议在这种情况下关闭屏幕。有关关闭付费墙屏幕的详情,请参阅响应按钮操作

完成网页支付导航

当尝试为特定产品打开网页付费墙后,将调用此方法。这包括导航成功和失败两种情况:

void paywallViewDidFinishWebPaymentNavigation(AdaptyUIPaywallView view, 
                                               AdaptyPaywallProduct? product, 
                                               AdaptyError? error) {
}

参数:

参数描述
product打开网页付费墙时对应的 AdaptyPaywallProduct。可以为 null
error如果网页付费墙导航失败,则为 AdaptyError 对象;如果导航成功,则为 null
事件示例(点击展开)
// 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"
    }
  }
}

购买失败

当购买失败时(例如,由于支付问题或网络错误),将调用此方法。对于用户主动取消或待处理的交易,不会触发此方法——这些情况由 paywallViewDidFinishPurchase 处理:

void paywallViewDidFailPurchase(AdaptyUIPaywallView view, 
                                AdaptyPaywallProduct product, 
                                AdaptyError error) {
}
事件示例(点击展开)
{
  "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"
    }
  }
}

开始恢复购买

如果用户发起恢复购买流程,将调用此方法:

void paywallViewDidStartRestore(AdaptyUIPaywallView view) {
}

恢复购买成功

如果恢复购买成功,将调用此方法:

void paywallViewDidFinishRestore(AdaptyUIPaywallView view, AdaptyProfile profile) {
}
事件示例(点击展开)
{
  "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"
      }
    ]
  }
}

如果用户拥有所需的 accessLevel,我们建议关闭屏幕。请参阅订阅状态主题了解如何检查,以及响应按钮操作主题了解如何关闭付费墙屏幕。

恢复购买失败

如果恢复购买失败,将调用此方法:

void paywallViewDidFailRestore(AdaptyUIPaywallView view, AdaptyError error) {
}
事件示例(点击展开)
{
  "error": {
    "code": "restore_failed",
    "message": "Purchase restoration failed",
    "details": {
      "underlyingError": "No previous purchases found"
    }
  }
}

数据获取与渲染

产品加载错误

如果初始化时未传入产品数组,AdaptyUI 将自行从服务器获取所需对象。如果此操作失败,AdaptyUI 将通过调用此方法报告错误:

void paywallViewDidFailLoadingProducts(AdaptyUIPaywallView view, AdaptyError error) {
}
事件示例(点击展开)
{
  "error": {
    "code": "products_loading_failed",
    "message": "Failed to load products from the server",
    "details": {
      "underlyingError": "Network timeout"
    }
  }
}

渲染错误

如果在界面渲染过程中发生错误,将通过调用此方法进行报告。默认情况下(自 v3.15.2 起),发生渲染错误时付费墙会自动关闭,但如有需要,您可以覆盖此行为。

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
}
事件示例(点击展开)
{
  "error": {
    "code": "rendering_failed",
    "message": "Failed to render paywall interface",
    "details": {
      "underlyingError": "Invalid paywall configuration"
    }
  }
}

在正常情况下,此类错误不应发生,如果您遇到此类错误,请告知我们。