Quick Start
Platform Examples
Checkout Customization
Mobile Recipes
start(...) 调用中,并内置已放弃会话恢复功能。只有在这些 SDK 都不适用于你的技术栈时,才应使用手动 WebView。前置条件
将 Dodo Payments 集成到移动应用之前,请确保你具备以下条件:- Dodo Payments 账户:已启用且具有 API 访问权限的商户账户
- API 凭证:从控制面板获取的 API key 和 webhook secret key
- 移动应用项目:Android、iOS、React Native 或 Flutter 应用
- 后端服务器:用于安全地处理结账会话创建
集成流程
移动端集成遵循安全的 4 步流程:后端处理 API 调用,移动应用管理用户体验。status 仅是告诉界面向用户显示什么的 UI 提示。始终通过后端的 payment.succeeded / subscription.active webhook 授予访问权限,绝不能仅依据移动端结果。Backend: Create Checkout Session
Checkout Session API Docs
Mobile: Get Checkout URL
- iOS (Swift)
- Android (Kotlin)
- React Native (JavaScript)
- Flutter (Dart)
Mobile: Open Checkout in Browser
Pick your mobile SDK
Backend: Handle Payment Completion
选择 SDK
每个移动端 SDK 都公开相同的契约:一次start(...) 调用即可在平台的原生浏览器界面中打开 Dodo 托管的结账页面,并返回一个类型化的 CheckoutResult,其 status 为 succeeded、failed、cancelled、pending 或 expired。它们都不会保存 API key 或调用 Dodo Payments API,并且全部支持已放弃会话恢复。
Android
com.dodopayments.api:checkout-android 会打开 Chrome Custom Tab。需要 minSdk 23。iOS
dodopayments-mobile-sdk-ios 会打开 SFSafariViewController。需要 iOS 16+。React Native
@dodopayments/react-native-checkout 是同时运行于两个原生核心之上的 Turbo Module。需要 React Native 0.76+。Flutter
dodopayments_checkout 是同时运行于两个原生核心之上的 Pigeon channel。需要 Flutter 3.44+。注册回调 URL Scheme
四个 SDK 都会通过你选择的自定义 URL scheme 将控制权交还给应用,例如myapp://checkout/return。请在每个平台上注册一次:
- Android
- iOS
- Expo
checkout_url(Android Custom Tabs / iOS SFSafariViewController),拦截导航到 return_url 的过程,然后读取 status 和 payment_id 查询参数。上述 SDK 会为你完成这些操作。外观自定义
每个 SDK 都接受start(...) / CheckoutParams 上的可选 customization 参数,用于控制原生浏览器界面的外观和行为,包括工具栏、按钮和呈现方式。这与结账页面自身的主题不同;后者需要在服务器端通过结账会话上的 customization.theme_config 进行配置。
选项按平台分组,因为 Android 的 Custom Tab 和 iOS 的 SFSafariViewController 提供的原生控件不同。所有字段均为可选;完全省略 customization 时,将使用各平台的默认外观。
Android - Custom Tab
Android - Custom Tab
- React Native
- Flutter
- Android (Kotlin)
- iOS (Swift)
结账页面自定义
上面的外观自定义部分控制原生浏览器界面,包括工具栏、按钮和配色方案。结账页面本身(显示哪些字段、使用何种主题、显示哪些付款方式)是在创建结账会话时于服务器端配置的。这些参数对移动端转化率影响最大。 以下参数分别位于结账会话请求的三个不同位置;位置列会告诉你每个参数所属的对象。配置错误是最常见的问题:放在错误对象中的参数会被静默忽略。
show_order_details: false moves the contact and payment fields above the fold, instead of behind the order summary.
minimal_address: true 设置为仅收集邮政编码,而不是完整的街道、城市和州字段:

minimal_address: true reduces the billing address to a single postcode field.
theme: "system",使结账页面遵循设备的浅色或深色模式偏好:

With theme: system, the checkout follows the device's light or dark appearance automatically.
Full checkout session parameter reference
移动端优化方案
以下每个方案都是完整的结账会话请求正文。选择与你的场景匹配的方案,替换产品 ID,然后将其传递给后端的会话创建端点。Minimal Mobile Checkout - fastest path to payment
Minimal Mobile Checkout - fastest path to payment
- Node.js SDK
- Python SDK
One-Click Returning Customer - saved card, instant confirmation
One-Click Returning Customer - saved card, instant confirmation
confirm: true,即可完全跳过结账表单。- Node.js SDK
- Python SDK
status 仅是 UI 提示。请通过监听后端的 payment.succeeded webhook 来确认访问权限。Subscription with Free Trial - trial before first charge
Subscription with Free Trial - trial before first charge
- Node.js SDK
- Python SDK
subscription.active webhook 时授予功能访问权限,而不是在移动 SDK 返回结果时授予。完整的 webhook 流程请参阅订阅集成指南。On-Demand Mandate - save a card for future variable charges
On-Demand Mandate - save a card for future variable charges
- Node.js SDK
- Python SDK
移动端订阅流程
订阅通过与一次性付款相同的结账会话流程创建:移动 SDK 打开托管结账页面,客户完成订阅,应用处理深层链接返回。之后,订阅生命周期完全由后端管理。常规周期性订阅
对于固定间隔计费(月付、年付),请使用订阅产品和深层链接return_url 创建结账会话。订阅确认后,后端会收到 subscription.active。
按需订阅
按需订阅允许你仅授权一次客户的付款方式,之后再收取不同金额,适用于钱包充值、随用随付以及无法提前确定扣款金额的任何场景。完整请求正文请参阅上文的 按需授权 方案。 移动端的关键注意事项:- 设置
show_on_demand_tag: false,使结账页面不显示“订阅”或“按需”字样。对于卡片令牌化场景,客户并不期待看到订阅术语。 - 授权完成后,后端会收到
subscription.active。请保存subscription_id,之后的所有扣款都需要使用它。
带免费试用期的订阅
在结账会话中传入subscription_data.trial_period_days,即可在第一个计费周期之前提供试用期。客户在注册试用时授权付款方式;试用期结束后会自动进行首次扣款。完整请求正文请参阅上文的带免费试用期的订阅方案。
升级与降级
计划变更通过后端的 API 完成,而不是创建新的结账会话。Dodo Payments 会自动计算按比例计费。若要为客户提供自助服务选项,请嵌入或链接到 Customer Portal。Subscription Integration Guide
On-Demand Subscriptions
Upgrade / Downgrade
Customer Portal
减少结账流失
移动端结账的放弃率高于网页端:屏幕更小、干扰更多、表单更长都会造成影响。最快的改进来自结账会话本身的配置。优化表单
预填充客户数据
客户无需输入的每个字段,都会降低其放弃结账的可能性:- 新客户:从身份验证会话中设置
customer.email和customer.name。 - 回访客户:设置
customer.customer_id,自动预填充所有已存储的信息。 - 货币:始终同时传入
billing_currency和billing_address.country。
恢复工具
Abandoned Cart Recovery
Payment Retries
Subscription Dunning
Recovery Overview
最佳实践
- 安全性:绝不要将 API key 放入应用中。请在后端创建结账会话,并仅将生成的
checkout_url传递给客户端。 - 权威性:将
CheckoutResult.status视为 UI 提示。只有后端确认付款后才授予访问权限。 - 用户体验:后端创建会话时显示加载状态,并将
cancelled作为正常结果处理,而不是错误。 - 测试:使用 test mode 和测试卡,并在真实设备和模拟器上验证返回 URL 的往返流程。
- 转化率:设置
show_order_details: false和minimal_address: true,以获得最佳移动端结账完成率。将付款方式移到首屏上方并减少表单字段,是影响最大的两项改动。 - 货币:始终显式传入
billing_currency和billing_address.country;缺少其中任意一个时,Adaptive Currency 可能会根据客户 IP 地址更改计费货币。 - 按需计费:将按需订阅用于卡片令牌化时设置
show_on_demand_tag: false。使用钱包充值流程的客户不会期待看到“订阅”字样。 - 恢复:在 Dodo Payments 控制面板中启用已放弃购物车恢复功能,自动重新触达未完成结账的客户。
故障排除
常见问题
- 从未收到回调:
returnUrl中的 scheme 必须与注册的 scheme 匹配。在 Android 上,它是dodoCallbackSchememanifest 占位符;在 iOS 和 React Native 上,它是Info.plistURL type。 - 结账返回浏览器而不是应用(iOS):你尚未转发传入的 URL。请从
.onOpenURL、scene(_:openURLContexts:)或 React NativeLinkinglistener 中调用DodoCheckout.handleOpenURL(url)。 - Android 上出现
PLATFORM_ERROR:通常是 scheme 不匹配。若MainActivity将android:taskAffinity=""设置为默认的flutter create,也可能出现此问题,因为某些 OEM 构建会丢失正在进行的结账会话。 ALREADY_IN_PROGRESS:已有结账会话处于打开状态。请等待或关闭之前的会话,然后再启动新的会话。- 构建因未解析的占位符失败:你添加了 Android SDK,但从未设置
manifestPlaceholders["dodoCallbackScheme"]。 - 付款成功但未授予访问权限:如果你依据移动端结果授予权限,这是预期行为。请改为根据
payment.succeeded/subscription.activewebhook 授予权限。 - 移动端未显示 Apple Pay / Google Pay:结账页面正在嵌入式 WebView(
WKWebView/ AndroidWebView)中加载,这会阻止电子钱包,并可能破坏 3-D Secure。请改用 SDK 或系统浏览器(Custom Tabs /SFSafariViewController)打开。
