处理 flow 与付费墙事件 - Capacitor

本指南介绍购买、恢复、产品选择及流程渲染的事件处理。你也可以设置按钮处理(关闭流程、打开链接、自定义操作等)。详情请参阅按钮操作处理指南

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

要在移动应用中控制或监听流程界面上发生的事件,请实现 view.setEventHandlers 方法:

每个事件只能设置一个处理器:多次调用 setEventHandlers 会覆盖你提供的处理器,同时替换掉那些特定事件的默认处理器和之前设置的处理器。未设置的处理器保持默认行为。setEventHandlers 返回一个取消订阅的函数,view.dismiss() 会清除所有处理器。


const view = await createFlowView(flow);

const unsubscribe = await view.setEventHandlers({
  onCloseButtonPress() {
    return true; // close the flow (default behavior)
  },
  onAndroidSystemBack() {
    return true; // close the flow; by default, it stays open
  },
  onPurchaseCompleted(purchaseResult, product) {
    return purchaseResult.type === 'success'; // close the flow on a successful purchase, keep it open for cancelled or pending purchases
  },
  onPurchaseStarted(product) { /***/ },
  onPurchaseFailed(error, product) { /***/ },
  onRestoreCompleted(profile) { /***/ },
  onRestoreFailed(error) { /***/ },
  onProductSelected(productId) { /***/ },
  onError(error) { /***/ },
  onLoadingProductsFailed(error) { /***/ },
  onUrlPress(url, openIn) {
    adapty.openWebUrl({ url, openIn }).catch(console.warn); // same as the SDK default
    return false; // keep the flow open
  },
  onAppeared() { /***/ },
  onDisappeared() { /***/ },
  onWebPaymentNavigationFinished() { /***/ },
});
事件示例(点击展开)

以下示例展示了每个处理程序中可用的属性,注释中提供了说明性的值。

// onUrlPress
url;    // 'https://example.com/terms'
openIn; // 'browser_in_app' or 'browser_out_app'

// onCustomAction
actionId; // 'login'

// onProductSelected
productId; // 'premium_monthly'

// onPurchaseStarted, onPurchaseCompleted, onPurchaseFailed
product.vendorProductId;        // 'premium_monthly'
product.localizedTitle;         // 'Premium Monthly'
product.localizedDescription;   // 'Premium subscription for 1 month'
product.price?.amount;          // 9.99
product.price?.currencyCode;    // 'USD'
product.price?.localizedString; // '$9.99'

// onPurchaseCompleted
purchaseResult.type; // 'success', 'pending', or 'user_cancelled'
if (purchaseResult.type === 'success') {
  purchaseResult.profile.accessLevels['premium']?.isActive; // true
}

// onRestoreCompleted
profile.accessLevels['premium']?.isActive; // true

// onPurchaseFailed, onRestoreFailed, onError, onLoadingProductsFailed
error.message; // 'Purchase failed due to insufficient funds'

您可以只注册需要的事件处理程序,忽略不需要的。这样就不会创建多余的事件监听器。所有事件处理程序均为可选。

事件处理程序返回一个布尔值。如果返回 true,则认为展示流程已完成,流程屏幕随即关闭,并移除该视图的所有事件监听器。 某些事件处理器具有默认行为,您可以根据需要进行覆盖:

  • onCloseButtonPress:当用户按下关闭按钮时,关闭流程。
  • onUrlPress:通过 adapty.openWebUrl 在原生浏览器中打开被点击的 URL,遵循编辑工具中设置的 Open in 选项,并保持流程开启。
  • onAndroidSystemBack:当用户按下 Back 按钮时,保持流程开启。返回 true 可关闭流程。
  • onPurchaseCompleted:购买完成后保持流程开启。返回 true 可关闭流程。
  • onRestoreCompleted:成功恢复购买后保持流程开启。返回 true 可关闭流程。
  • onError:如果流程渲染失败,则关闭流程。

事件处理程序

事件处理器描述
onCustomAction当用户执行自定义操作时触发,例如点击自定义按钮
onUrlPress当用户点击流程中的 URL 时触发。
onAndroidSystemBack当用户点击 Android 系统的 Back 按钮时触发。默认情况下流程保持打开;返回 true 可关闭它。
onCloseButtonPress当关闭按钮可见且用户点击它时触发。建议在此处理器中关闭流程页面。
onPurchaseCompleted购买完成时触发,无论结果是成功、用户取消还是待审批。购买成功时会提供更新后的 AdaptyProfile。用户取消及待处理付款(如需家长审批)会触发此事件,而非 onPurchaseFailed
onPurchaseStarted当用户点击”购买”操作按钮以开始购买流程时触发。
onPurchaseFailed因错误导致购买失败时触发(如付款限制、无效产品、网络故障、交易验证失败等)。用户取消或待处理付款不会触发此事件,这些情况会触发 onPurchaseCompleted
onRestoreStarted当用户开始恢复购买流程时触发。
onRestoreCompleted购买恢复成功时触发,并提供更新后的 AdaptyProfile。如果用户已具备所需的 accessLevel,建议关闭页面。请参阅订阅状态了解如何检查。
onRestoreFailed恢复流程失败时触发,并提供 AdaptyError
onProductSelected当用户在流程视图中选择任意产品时触发,可用于监控用户在购买前的选择。
onError视图渲染过程中发生错误时触发,并提供 AdaptyError。此类错误本不应出现,如果遇到,请告知我们。
onLoadingProductsFailed产品加载失败时触发,并提供 AdaptyError。如果在创建视图时未设置 prefetchProducts: true,AdaptyUI 会自行从服务器获取所需对象。
onAppeared当流程展示给用户时触发。在 iOS 上,当用户点击流程中的 Web 付费墙按钮 且 Web 付费墙在应用内浏览器中打开时,也会触发此事件。
onDisappeared当用户关闭流程时触发。在 iOS 上,当从流程中在应用内浏览器打开的 Web 付费墙 从屏幕消失时,也会触发此事件。
onWebPaymentNavigationFinished尝试打开 Web 付费墙 进行购买后触发,无论成功与否。
onRequestAppReview为流程中的应用评价请求预留。目前流程尚不会触发应用评价请求,无需实现。
onAnalytics为流程中的自定义分析事件预留。目前流程尚不会向你的代码发送这些事件,无需实现。
onRequestPermission为流程中的系统权限请求(如推送通知或相机访问)预留。目前流程尚不会触发权限请求,无需实现。
onObserverPurchaseInitiated仅限观察者模式:当用户在流程中点击购买按钮时触发。Adapty 不会执行购买——请使用你自己的购买代码完成购买,然后将交易上报给 Adapty。详见下方在观察者模式下处理购买
onObserverRestoreInitiated仅限观察者模式:当用户在流程中点击恢复按钮时触发。Adapty 不会执行恢复——请自行恢复,然后上报所有已恢复的交易。详见下方在观察者模式下处理购买

在观察者模式下处理购买

如果你以观察者模式observerMode: true)激活了 SDK 并展示 Adapty 渲染的流程,SDK 不会为你执行购买操作。当用户点击购买或恢复按钮时,SDK 会调用 onObserverPurchaseInitiatedonObserverRestoreInitiated,你可以用自己的代码来处理购买或恢复逻辑。完整设置请参阅在观察者模式下展示流程

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

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

如需在移动应用中控制或监控付费墙界面上发生的流程,请实现 view.setEventHandlers 方法:


const view = await createPaywallView(paywall);

const unsubscribe = view.setEventHandlers({
  onCloseButtonPress() {
    console.log('User closed paywall');
    return true; // Allow the paywall to close
  },
  onAndroidSystemBack() {
    console.log('User pressed back button');
    return true; // Allow the paywall to close
  }, 
  onAppeared() {
    console.log('Paywall appeared');
    return false; // Don't close the paywall
  }, 
  onDisappeared() {
    console.log('Paywall disappeared');
  },
  onPurchaseCompleted(purchaseResult, product) {
    console.log('Purchase completed:', purchaseResult);
    return purchaseResult.type !== 'user_cancelled'; // Close if not cancelled
  },
  onPurchaseStarted(product) {
    console.log('Purchase started:', product);
    return false; // Don't close the paywall
  },
  onPurchaseFailed(error, product) {
    console.error('Purchase failed:', error);
    return false; // Don't close the paywall
  },
  onRestoreCompleted(profile) {
    console.log('Restore completed:', profile);
    return true; // Close the paywall after successful restore
  },
  onRestoreFailed(error) {
    console.error('Restore failed:', error);
    return false; // Don't close the paywall
  },
  onProductSelected(productId) {
    console.log('Product selected:', productId);
    return false; // Don't close the paywall
  },
  onRenderingFailed(error) {
    console.error('Rendering failed:', error);
    return false; // Don't close the paywall
  },
  onLoadingProductsFailed(error) {
    console.error('Loading products failed:', error);
    return false; // Don't close the paywall
  },
  onUrlPress(url) {
    window.open(url, '_blank');
    return false; // Don't close the paywall
  },
});
事件示例(点击展开)
// onCloseButtonPress
{
  "event": "close_button_press"
}

// onAndroidSystemBack
{
  "event": "android_system_back"
}

// onAppeared
{
  "event": "paywall_shown"
}

// onDisappeared
{
  "event": "paywall_closed"
}

// onUrlPress
{
  "event": "url_press",
  "url": "https://example.com/terms"
}

// onCustomAction
{
  "event": "custom_action",
  "actionId": "login"
}

// onProductSelected
{
  "event": "product_selected",
  "productId": "premium_monthly"
}

// onPurchaseStarted
{
  "event": "purchase_started",
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  }
}

// onPurchaseCompleted - Success
{
  "event": "purchase_completed",
  "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"
  }
}

// onPurchaseCompleted - Cancelled
{
  "event": "purchase_completed",
  "purchaseResult": {
    "type": "user_cancelled"
  },
  "product": {
    "vendorProductId": "premium_monthly",
    "localizedTitle": "Premium Monthly",
    "localizedDescription": "Premium subscription for 1 month",
    "localizedPrice": "$9.99",
    "price": 9.99,
    "currencyCode": "USD"
  }
}

// onPurchaseFailed
{
  "event": "purchase_failed",
  "error": {
    "code": "purchase_failed",
    "message": "Purchase failed due to insufficient funds",
    "details": {
      "underlyingError": "Insufficient funds in account"
    }
  }
}

// onRestoreCompleted
{
  "event": "restore_completed",
  "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"
      }
    ]
  }
}

// onRestoreFailed
{
  "event": "restore_failed",
  "error": {
    "code": "restore_failed",
    "message": "Purchase restoration failed",
    "details": {
      "underlyingError": "No previous purchases found"
    }
  }
}

// onRenderingFailed
{
  "event": "rendering_failed",
  "error": {
    "code": "rendering_failed",
    "message": "Failed to render paywall interface",
    "details": {
      "underlyingError": "Invalid paywall configuration"
    }
  }
}

// onLoadingProductsFailed
{
  "event": "loading_products_failed",
  "error": {
    "code": "products_loading_failed",
    "message": "Failed to load products from the server",
    "details": {
      "underlyingError": "Network timeout"
    }
  }
}

您可以只注册需要的事件处理器,无需注册的可以忽略。这样就不会创建多余的事件监听器。所有事件处理器均为可选。

事件处理器返回一个布尔值。若返回 true,则视为展示流程已完成,付费墙页面将关闭,该视图的所有事件监听器也会随之移除。 某些事件处理程序具有默认行为,您可以根据需要进行覆盖:

  • onCloseButtonPress:点击关闭按钮时关闭付费墙。
  • onAndroidSystemBack:按下 Back 按钮时关闭付费墙。
  • onRestoreCompleted:恢复成功后关闭付费墙。
  • onPurchaseCompleted:除非用户取消,否则关闭付费墙。
  • onRenderingFailed:付费墙渲染失败时关闭付费墙。
  • onUrlPress:在系统浏览器中打开 URL,并保持付费墙开启。

事件处理器

事件处理程序描述
onCustomAction当用户执行自定义操作时触发,例如点击自定义按钮
onUrlPress当用户点击付费墙中的 URL 时触发。
onAndroidSystemBack当用户点击 Android 系统 Back 按钮时触发。
onCloseButtonPress当关闭按钮可见且用户点击时触发。建议在此处理程序中关闭付费墙屏幕。
onPurchaseCompleted购买完成时触发,无论成功、用户取消还是等待审批。购买成功时提供更新后的 AdaptyProfile。用户取消和待处理支付(如需要家长批准)会触发此事件,而非 onPurchaseFailed
onPurchaseStarted当用户点击”购买”操作按钮开始购买流程时触发。
onPurchaseCancelled当用户发起购买流程后手动中断(取消支付对话框)时触发。
onPurchaseFailed购买因错误失败时触发(如支付限制、无效产品、网络故障、交易验证失败)。用户取消或待处理支付不会触发此事件,这些情况会触发 onPurchaseCompleted
onRestoreStarted当用户开始购买恢复流程时触发。
onRestoreCompleted购买恢复成功时触发,并提供更新后的 AdaptyProfile。如果用户拥有所需的 accessLevel,建议关闭屏幕。请参阅订阅状态主题了解如何进行检查。
onRestoreFailed恢复流程失败时触发,并提供 AdaptyError
onProductSelected付费墙视图中任意产品被选择时触发,允许您监控用户在购买前的选择。
onAppeared付费墙视图出现在屏幕上时触发。在 iOS 上,当用户点击付费墙内的网页付费墙按钮且网页付费墙在应用内浏览器中打开时,也会触发此事件。
onDisappeared付费墙视图从屏幕消失时触发。在 iOS 上,当从付费墙在应用内浏览器中打开的网页付费墙从屏幕消失时,也会触发此事件。
onRenderingFailed视图渲染期间发生错误时触发,并提供 AdaptyError。此类错误不应出现,如遇到请告知我们。
onLoadingProductsFailed产品加载失败时触发,并提供 AdaptyError。如果您在创建视图时未设置 prefetchProducts: true,AdaptyUI 将自行从服务器获取所需对象。