App 审核质量要求
Stripe 会根据一套全面的质量要求审核提交到 marketplace 的每个应用。在开发之前了解这些标准可以节省时间并减少审核轮次。
概述
Stripe App 审核在六个关键领域评估您的应用:
- 透明定价, 明确传达费用
- 应用功能, 可靠性和完整性
- 开发者标准, 代码质量和 API 使用
- UX 质量, 用户界面和体验标准
- 安全性, 数据保护和安全实践
- 法律合规, 隐私和监管要求
透明定价
您的应用必须向用户清晰传达所有费用:
- 价格披露:所有价格必须在 marketplace listing 中提前说明
- 无隐藏费用:用户安装后不得遇到意外收费
- 试用条款:如果提供试用,请清晰说明期限和到期后的情况
- 升级流程:任何追加销售或升级提示必须不具侵扰性且明确为可选
- 货币:尽可能以用户本地货币显示价格
Caution
隐瞒定价或在未获明确同意的情况下向用户收费的应用将被立即拒绝。
日期和时间格式
您应用中显示的所有日期和时间必须遵循 Stripe Dashboard 惯例:
- 尽可能使用用户的 locale 进行日期格式化
- 以用户本地时区显示时间
- 对最近的事件使用相对时间戳(例如:“2小时前”)
- 对较旧的事件使用包含完整日期和时间的绝对时间戳
- 对任何面向 API 的日期字段遵循 ISO 8601
// 好: 使用 Stripe 的日期格式化工具import { formatDate, formatRelativeTime } from '@stripe/ui-extension-sdk/utils';
const formattedDate = formatDate(timestamp); // 根据 localeconst relativeTime = formatRelativeTime(timestamp); // "2小时前"应用设置
如果您的应用需要配置:
- 提供可从应用视口访问的专用设置视图
- 尽可能预填充合理的默认值
- 使用清晰的错误消息验证所有用户输入
- 允许用户在不重新安装应用的情况下更新设置
- 使用 Stripe Secret Store API 跨会话持久化设置
Sandbox 支持
您的应用必须在 Stripe 的 sandbox(测试)模式下正确工作:
- 测试模式兼容性:所有功能必须在测试模式下运行
- 测试数据:使用展示应用功能的真实测试数据
- sandbox 中无 live 数据:永远不要在测试模式下暴露生产数据
- 优雅处理:如果某项功能在 sandbox 中不可用,请显示清晰的说明消息
- 在 manifest 中设置
sandbox_install_compatible: true
{ "sandbox_install_compatible": true}应用功能
可靠性
- 应用在正常使用过程中不得崩溃或冻结
- 所有宣传的功能必须按描述工作
- 网络错误必须得到优雅处理,并提供重试选项
- 应用在后台操作期间必须保持响应
完整性
- 没有占位内容、“即将推出”功能或失效链接
- 所有 UI 元素必须可用, 没有无效按钮或不活动控件
- 帮助文本和文档链接必须指向有效页面
- 卸载必须干净地删除所有应用数据和 webhooks
性能
- UI 必须在标准连接上 3 秒内渲染
- 后台同步操作不得阻塞 UI
- 大型数据集必须使用分页或懒加载
- 最小化 API 调用以避免速率限制
开发者标准
API 使用
- 使用 Stripe API 的最新稳定版本
- 遵循 Stripe API 关于分页、错误处理和幂等性的最佳实践
- 不超过速率限制, 为重试实现指数退避
- 使用 webhooks 进行事件驱动更新,而非轮询
代码质量
- 生产构建中没有控制台错误或警告
- 提交前删除所有调试日志
- 处理所有边缘情况(空状态、缺失数据、网络故障)
- 遵循 Stripe 组件库模式以保持一致的 UI
版本控制
- 使用语义化版本控制(MAJOR.MINOR.PATCH)
- 在版本更新中记录重大变更
- 尽可能保持向后兼容性
UX 质量
广告
- 无广告:您的应用不得显示任何形式的广告
- 无交叉推广:不得在应用 UI 中推广其他产品或服务
- 品牌内容:只显示您自己的品牌标识,不显示第三方品牌(集成合作伙伴如 Brevo 除外)
语言和内容
- 一致的语言:在整个应用中使用一致的术语
- 专业语气:与 Stripe Dashboard 的专业、简洁沟通风格保持一致
- 无行话:避免商家可能不理解的技术术语
- 拼写检查:确保所有文本无拼写和语法错误
- 仅英文:marketplace 应用的所有用户可见文本必须为英文
确认对话框
对于破坏性或重要操作需要用户确认:
// 好: 破坏性操作前确认const handleDisconnect = async () => { const confirmed = await showConfirmation({ title: 'Disconnect Brevo Integration', message: 'This will stop syncing customer data to Brevo. You can reconnect at any time.', confirmLabel: 'Disconnect', cancelLabel: 'Cancel', destructive: true, });
if (confirmed) { await disconnectIntegration(); }};需要确认的操作:
- 断开集成连接
- 删除已同步数据
- 更改影响数据流的设置
- 将配置重置为默认值
加载状态
始终为异步操作显示加载指示器:
// 好: 数据获取期间显示加载状态const CustomerSyncStatus = () => { const { data, isLoading, error } = useSyncStatus();
if (isLoading) { return <Spinner label="Loading sync status..." />; }
if (error) { return <Banner type="critical" title="Failed to load sync status"> {error.message} </Banner>; }
return <SyncStatusDisplay data={data} />;};要求:
- 数据加载期间显示 spinner 或骨架屏
- 表单提交期间禁用按钮
- 长时间运行操作显示进度指示器
- 加载时不显示空白屏幕
错误消息
提供清晰、可操作的错误消息:
// 差: 通用错误"Something went wrong"
// 好: 具体且可操作"Unable to sync customer data to Brevo. Please verify your Brevo API keyin Settings and try again."错误消息指南:
- 用通俗语言解释发生了什么
- 建议用户可以采取的具体解决步骤
- 提供重试失败操作的方式
- 记录详细错误信息用于调试(不显示给用户)
- 在适用时包含错误代码供支持参考
安全性
Secret Store API
对所有敏感数据存储使用 Stripe 的 Secret Store API:
import { createHttpClient, STRIPE_API_KEY } from '@stripe/ui-extension-sdk/http_client';
// 好: 使用 Secret Store API 存储 secretsconst storeBrevoApiKey = async (apiKey: string) => { const stripe = createHttpClient(STRIPE_API_KEY); await stripe.apps.secrets.create({ name: 'brevo_api_key', payload: apiKey, scope: { type: 'account' }, });};
// 好: 从 Secret Store 检索 secretsconst getBrevoApiKey = async () => { const stripe = createHttpClient(STRIPE_API_KEY); const secret = await stripe.apps.secrets.find({ name: 'brevo_api_key', scope: { type: 'account' }, }); return secret.payload;};绝不在以下位置存储敏感数据:
- Local storage 或 session storage
- Cookies
- URL 参数
- 源代码中的硬编码值
- 纯文本配置文件
密码学
- 无自定义加密:不要实现您自己的加密算法
- 使用 Stripe 的内置安全原语(Secret Store、signing secrets)
- 对所有外部 API 调用使用 HTTPS
- 处理前验证所有 webhook signatures
数据处理
- 只请求应用实际需要的权限
- 不存储超出功能所需的 Stripe 数据
- 实施与隐私政策一致的数据保留政策
- 为用户提供请求数据删除的机制
法律合规
隐私政策
您的应用必须有公开可访问的隐私政策,涵盖:
- 应用从 Stripe 收集哪些数据
- 数据如何存储、处理和共享
- 数据保留和删除政策
- 用户对其数据的权利
- 隐私查询的联系信息
- 遵守适用法规(GDPR、CCPA 等)
服务条款
- 为您的应用提供清晰的服务条款
- 不包含与 Stripe 服务条款冲突的条款
- 明确说明任何使用限制
法规合规
- 遵守所有适用的数据保护法规
- 实施适当的数据处理协议
- 支持数据可移植性和删除请求
- 维护数据访问和处理的审计日志
审核流程时间表
| 阶段 | 时长 |
|---|---|
| 初始提交 | 5-10 个工作日 |
| 修订审核 | 3-7 个工作日 |
| 最终审批 | 1-2 个工作日 |
| 发布 | 批准后立即 |
Tip
在一次修订中解决所有审核反馈,以避免多个审核周期。Stripe 团队为每个发现的问题提供具体、可操作的反馈。
常见拒绝原因
- 缺少错误处理, 应用在网络错误或意外数据时崩溃
- 加载状态不足, 数据获取期间出现空白屏幕
- 定价不清晰, listing 中未完全披露价格
- 过多权限, 请求应用不需要的权限
- Sandbox 模式失效, 应用在测试模式下不运行
- 安全问题, 在 Secret Store API 之外存储 secrets
- 缺少隐私政策, 没有可访问的隐私政策 URL
- 功能不完整, “即将推出”功能或占位内容