---
title: "App 审核质量要求 | Tajo"
description: "Stripe App 必须满足的质量、安全、UX 和法律标准，才能通过审核"
url: https://tajo.io/zh-cn/docs/stripe-apps/review-requirements/
markdown: https://tajo.io/zh-cn/docs/stripe-apps/review-requirements.md
lang: zh-CN
author: "Set Noa"
author_url: https://tajo.io/zh-cn/set-noa/
robots: noindex
---

申请抢先体验

请输入您的名字和公司电子邮箱地址。我们会发送确认 Tajo 访问申请的链接。

# App 审核质量要求

[Set Noa](https://tajo.io/zh-cn/set-noa/)

对于提交到应用市场的每一个 App，Stripe 都会按照一整套质量要求进行审核。在开发前就吃透这些标准，可以节省时间，减少来回修改的次数。

Caution

**状态：计划中，尚未构建。** Tajo 没有 Stripe App，因此本章中的任何内容目前都无法安装。本页中的 app 标识、URL 和凭据都是用于示意的占位值，而不是可用的线上端点。

## 概览

Stripe App 审核会从六个关键维度评估你的 App：

1. **透明定价**，清晰传达费用
2. **App 功能**，可靠且完整
3. **开发规范**，代码质量与 API 使用方式
4. **UX 质量**，界面与体验标准
5. **安全**，数据保护与安全实践
6. **法律合规**，隐私与监管要求

## 透明定价

你的 App 必须向用户清楚说明所有费用：

- **定价披露**：所有价格都必须在应用市场的展示页面中提前写明
- **无隐藏费用**：用户在安装后不应遇到意料之外的收费
- **试用条款**：如果提供试用，要写清时长以及试用结束后会发生什么
- **升级流程**：任何加购或升级提示都必须不打扰用户，并明确标注为可选
- **货币**：尽可能以用户所在地的货币展示价格

Caution

隐瞒定价，或在没有明确同意的情况下向用户收费的 App，会被直接拒绝。

## 日期与时间格式

App 中显示的所有日期和时间都必须遵循 Stripe Dashboard 的惯例：

- 有条件时按用户所在区域设置格式化日期
- 按用户所在时区显示时间
- 近期事件使用相对时间戳（例如 “2 hours ago”）
- 较早的事件使用带完整日期和时间的绝对时间戳
- 面向 API 的日期字段一律遵循 ISO 8601

```typescript
// Good: Use Stripe's date formatting utilities
import { formatDate, formatRelativeTime } from '@stripe/ui-extension-sdk/utils';

const formattedDate = formatDate(timestamp); // Locale-aware
const relativeTime = formatRelativeTime(timestamp); // "2 hours ago"
```

## App 设置

如果你的 App 需要配置：

- 提供一个可从 App 视口进入的专用 **设置视图**
- 尽可能预填合理的默认值
- 校验所有用户输入，并给出清晰的错误提示
- 让用户无需重装 App 就能更新设置
- 使用 Stripe Secret Store API 跨会话保存设置

## 沙箱支持

你的 App 必须能在 Stripe 沙箱（测试）模式下正常工作：

- **测试模式兼容**：所有功能都必须能在测试模式下运行
- **测试数据**：使用贴近真实的测试数据来演示 App 功能
- **沙箱中不出现真实数据**：绝不能在测试模式下暴露生产数据
- **优雅降级**：如果某功能在沙箱中不可用，要显示清晰的说明解释原因
- 在清单文件中设置 `sandbox_install_compatible: true`

```json
{
  "sandbox_install_compatible": true
}
```

## App 功能

### 可靠性

- App 在正常使用过程中不得崩溃或卡死
- 所有宣传过的功能都必须与描述一致
- 网络错误必须被妥善处理，并提供重试选项
- 后台操作进行时，App 必须保持响应

### 完整性

- 不得有占位内容、“即将推出” 的功能或失效链接
- 所有 UI 元素都必须可用，不能有失效按钮或无响应控件
- 帮助文本和文档链接必须指向有效页面
- 卸载时必须彻底清除所有 App 数据和 Webhook

### 性能

- 在常规网络下，UI 必须在 3 秒内渲染完成
- 后台同步操作不得阻塞 UI
- 大数据集必须使用分页或懒加载
- 尽量减少 API 调用，避免触发限流

## 开发规范

### API 使用

- 使用最新的稳定版 Stripe API
- 在分页、错误处理和幂等性上遵循 Stripe API 最佳实践
- 不要超出限流阈值，重试时采用指数退避
- 用 Webhook 做事件驱动更新，而不是轮询

### 代码质量

- 生产构建中不得出现控制台错误或警告
- 提交前移除所有调试日志
- 处理所有边界情况（空状态、数据缺失、网络故障）
- 遵循 Stripe 组件库的模式，保持 UI 一致

### 版本管理

- 使用语义化版本（MAJOR.MINOR.PATCH）
- 在版本更新中记录破坏性变更
- 尽可能保持向后兼容

## UX 质量

### 广告

- **禁止广告**：你的 App 不得展示任何形式的广告
- **禁止交叉推广**：不得在 App 界面中推广其他产品或服务
- **品牌内容**：只能展示你自己的品牌标识，不得展示第三方品牌（Brevo 这类集成伙伴除外）

### 语言与内容

- **术语一致**：全 App 使用一致的术语
- **专业语气**：与 Stripe Dashboard 专业、简洁的沟通风格保持一致
- **不用黑话**：避免商家看不懂的技术术语
- **拼写检查**：确保所有文案没有拼写和语法错误
- **仅限英文**：应用市场 App 面向用户的所有文案都必须使用英文

### 确认对话框

对破坏性或影响较大的操作，必须要求用户确认：

```typescript
// Good: Confirm before destructive actions
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();
  }
};
```

需要确认的操作：

- 断开集成
- 删除已同步的数据
- 修改影响数据流的设置
- 把配置重置为默认值

### 加载状态

异步操作必须始终显示加载指示：

```typescript
// Good: Show loading state during data fetch
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} />;
};
```

要求：

- 数据加载期间显示加载动画或骨架屏
- 表单提交期间禁用按钮
- 长时间运行的操作要显示进度指示
- 加载时绝不能出现空白页面

### 错误提示

提供清晰、可操作的错误提示：

```typescript
// Bad: Generic error
"Something went wrong"

// Good: Specific and actionable
"Unable to sync customer data to Brevo. Please verify your Brevo API key
in Settings and try again."
```

错误提示准则：

- 用平实的语言说明发生了什么
- 给出用户可以采取的具体解决动作
- 提供重试失败操作的入口
- 记录详细的错误信息用于排查（不展示给用户）
- 需要时附上错误码，便于支持团队查询

## 安全

### Secret Store API

所有敏感数据都要用 Stripe 的 Secret Store API 存储：

```typescript
import { createHttpClient, STRIPE_API_KEY } from '@stripe/ui-extension-sdk/http_client';

// Good: Store secrets using the Secret Store API
const storeBrevoApiKey = async (apiKey: string) => {
  const stripe = createHttpClient(STRIPE_API_KEY);
  await stripe.apps.secrets.create({
    name: 'brevo_api_key',
    payload: apiKey,
    scope: { type: 'account' },
  });
};

// Good: Retrieve secrets from the Secret Store
const 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;
};
```

**绝不能** 把敏感数据存放在：

- 本地存储或会话存储
- Cookie
- URL 参数
- 源码中的硬编码值
- 明文配置文件

### 加密

- **不要自造加密**：不要自行实现加密算法
- 使用 Stripe 内置的安全原语（Secret Store、签名密钥）
- 所有外部 API 调用都走 HTTPS
- 处理前必须校验所有 Webhook 签名

### 数据处理

- 只申请 App 真正需要的权限
- 除功能必需的部分外，不要存储 Stripe 数据
- 落实与隐私政策一致的数据保留策略
- 提供让用户申请删除数据的途径

## 法律合规

### 隐私政策

你的 App 必须有一份可公开访问的隐私政策，涵盖：

- App 从 Stripe 收集哪些数据
- 数据如何存储、处理和共享
- 数据保留与删除策略
- 用户对自身数据享有的权利
- 隐私相关咨询的联系方式
- 对适用法规的合规情况（GDPR、CCPA 等）

### 服务条款

- 为你的 App 提供清晰的服务条款
- 不得包含与 Stripe 服务条款冲突的内容
- 明确写出任何使用限制或约束

### 监管合规

- 遵守所有适用的数据保护法规
- 签署合适的数据处理协议
- 支持数据可携带和删除请求
- 保留数据访问与处理的审计日志

## 审核流程时间线

| 阶段 | 时长 |
| --- | --- |
| 首次提交 | 5-10 个工作日 |
| 修订复审 | 3-7 个工作日 |
| 最终批准 | 1-2 个工作日 |
| 上架发布 | 批准后立即生效 |

Tip

把所有审核反馈在一次修订中全部处理完，避免多轮审核。对于发现的每个问题，Stripe 团队都会给出具体、可操作的反馈。

## 常见拒绝原因

1. **缺少错误处理**，App 在网络错误或数据异常时崩溃
2. **加载状态不足**，取数期间出现空白页面
3. **定价不清晰**，展示页面没有完整披露价格
4. **权限过度**，申请了 App 并不需要的权限
5. **沙箱模式不可用**，App 在测试模式下无法运行
6. **安全问题**，把密钥存放在 Secret Store API 之外
7. **缺少隐私政策**，没有可访问的隐私政策 URL
8. **功能不完整**，存在 “即将推出” 的功能或占位内容
