Android - 处理付费墙事件

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

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

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

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

如果您需要控制或监控购买界面上发生的流程,请实现 AdaptyUiEventListener 方法。

如果您希望在某些情况下保留默认行为,可以继承 AdaptyUiDefaultEventListener 并仅覆盖您想要更改的方法。

以下是 AdaptyUiDefaultEventListener 的默认实现。

用户生成的事件

产品选择

当某个产品被选中(由用户或系统)准备购买时,将调用此方法:

public override fun onProductSelected(
    product: AdaptyPaywallProduct,
    context: Context,
) {}
事件示例(点击展开)
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  }
}

开始购买

当用户发起购买流程时,将调用此方法:

public override fun onPurchaseStarted(
    product: AdaptyPaywallProduct,
    context: Context,
) {}
事件示例(点击展开)
{
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  }
}

该方法在观察者模式下不会被调用。详情请参阅 Android - 在观察者模式下展示付费墙编辑工具付费墙主题。

购买成功、取消或待处理

购买成功时,将调用此方法:

public override fun onPurchaseFinished(
    purchaseResult: AdaptyPurchaseResult,
    product: AdaptyPaywallProduct,
    context: Context,
) {
    if (purchaseResult !is AdaptyPurchaseResult.UserCanceled)
        context.getActivityOrNull()?.onBackPressed()
}
事件示例(点击展开)
// Successful purchase
{
  "purchaseResult": {
    "type": "Success",
    "profile": {
      "accessLevels": {
        "premium": {
          "id": "premium",
          "isActive": true,
          "expiresAt": "2024-02-15T10:30:00Z"
        }
      }
    }
  },
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  }
}

// Cancelled purchase
{
  "purchaseResult": {
    "type": "UserCanceled"
  },
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  }
}

// Pending purchase
{
  "purchaseResult": {
    "type": "Pending"
  },
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  }
}

我们建议在此情况下关闭屏幕。

该方法在观察者模式下不会被调用。详情请参阅 Android - 在观察者模式下展示付费墙编辑工具付费墙主题。

购买失败

如果购买因错误而失败,将调用此方法。这包括 Google Play Billing 错误(支付限制、无效产品、网络故障)、交易验证失败和系统错误。请注意,用户取消操作会触发带有取消结果的 onPurchaseFinished,而待处理支付不会触发此方法。

public override fun onPurchaseFailure(
    error: AdaptyError,
    product: AdaptyPaywallProduct,
    context: Context,
) {}
事件示例(点击展开)
{
  "error": {
    "code": "purchase_failed",
    "message": "Purchase failed due to insufficient funds",
    "details": {
      "underlyingError": "Insufficient funds in account"
    }
  },
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  }
}

该方法在观察者模式下不会被调用。详情请参阅 Android - 在观察者模式下展示付费墙编辑工具付费墙主题。

网页支付导航完成

此方法在尝试为特定产品打开网页付费墙后被调用。这包括成功和失败的导航尝试:

public override fun onFinishWebPaymentNavigation(
    product: AdaptyPaywallProduct?,
    error: AdaptyError?,
    context: Context,
) {}

参数:

参数描述
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"
    }
  }
}

恢复购买成功

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

public override fun onRestoreSuccess(
    profile: AdaptyProfile,
    context: Context,
) {}
事件示例(点击展开)
{
  "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 时关闭屏幕。请参阅订阅状态主题了解如何检查。

恢复购买失败

如果 Adapty.restorePurchases() 失败,将调用此方法:

public override fun onRestoreFailure(
    error: AdaptyError,
    context: Context,
) {}
事件示例(点击展开)
{
  "error": {
    "code": "restore_failed",
    "message": "Purchase restoration failed",
    "details": {
      "underlyingError": "No previous purchases found"
    }
  }
}

升级订阅

事件示例(点击展开)
{
  "product": {
    "vendorProductId": "premium_yearly",
    "localizedTitle": "Premium Yearly",
    "localizedDescription": "Premium subscription for 1 year",
    "localizedPrice": "$99.99",
    "price": 99.99,
    "currencyCode": "USD"
  },
  "subscriptionUpdateParams": {
    "replacementMode": "with_time_proration"
  }
}

数据获取与渲染

产品加载错误

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

public override fun onLoadingProductsFailure(
    error: AdaptyError,
    context: Context,
): Boolean = false
事件示例(点击展开)
{
  "error": {
    "code": "products_loading_failed",
    "message": "Failed to load products from the server",
    "details": {
      "underlyingError": "Network timeout"
    }
  }
}

如果您返回 true,AdaptyUI 将在 2 秒后重试请求。

渲染错误

如果在界面渲染过程中发生错误,将通过调用此方法进行报告:

public override fun onRenderingError(
    error: AdaptyError,
    context: Context,
) {}
事件示例(点击展开)
{
  "error": {
    "code": "rendering_failed",
    "message": "Failed to render paywall interface",
    "details": {
      "underlyingError": "Invalid paywall configuration"
    }
  }
}

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