CodeGym /课程 /ChatGPT Apps /Privacy Policy、Terms、Support:必备的法律页面

Privacy Policy、Terms、Support:必备的法律页面

ChatGPT Apps
第 18 级 , 课程 1
可用

1. 为什么必须提供 Privacy Policy、Terms 和 Support

先说句不那么讨喜的实话:对于 ChatGPT Store,公开的隐私政策和支持联系方式并非“礼貌”,而是硬性要求。OpenAI 指南明确写着,每个 App 都必须发布 Privacy Policy,清楚说明收集哪些数据以及如何使用,并提供支持联系信息。

但这件事并不只是为了“让审核员别再追着你”。这些文档同时解决多方面问题。

首先,这是为用户建立的基础信任。用户会看到,这个应用背后有真实的个人或公司,有游戏规则,也有可以反馈问题的渠道。在“又一个 AI 服务”每天冒出来的世界里,这已经是竞争优势。

其次,这是对你已在架构中完成事项的形式化。你在安全、日志、保留期、数据删除以及支付模块里做的决定,都应在文档里准确表达。如果你承诺“不会保存会话”,却把所有 tool‑input 永久记录在日志中,这不只是不好看——还可能引发严重投诉。

第三,这还是你与 OpenAI 之间的又一层契约。Store 实际上在说:“我们愿意把你的 App 展示给数百万人,但你必须如实说明你会如何处理他们的数据,并在出现问题时保持联络。”

总之,法律页面并不是“律师逼的”。它们是用来同步预期的:App 做什么、接触哪些数据、你承担何种责任,以及用户如何联系你。

2. 这些法律页面的 URL 在 ChatGPT App 中放在哪里

从技术上讲,ChatGPT App 的法律页面就是普通的公开 URL,你需要在应用元数据和 Store 列表里填写。指南里通常把它们称为 privacy_policy_urlterms_of_service_url 和支持联系方式。

这些 URL 需要满足几条简单但重要的要求:

  1. 它们位于你产品或公司的稳定域名上。 不要使用临时的 ngrok 链接,否则过几天 Store 就会把用户带向“无处可去”。
  2. 无需认证即可访问。 用户(以及审核员)应当能直接在浏览器打开,不需要登录或复杂操作。
  3. 内容应保持最新并与实际一致。 如果你改变了数据处理架构,迟早也要更新文本。

在我们的示例项目 GiftGenius 中,前端使用 Next.js 并部署在 Vercel。法律页面的合理位置就是如下路由:

  • /legal/privacy
  • /legal/terms
  • /support

本质上它们只是应用中的另外三张页面,但你会在提交 App 审核的表单里引用这些页面。

3. Privacy Policy:如实描述你如何处理数据

Privacy Policy 的角色

Privacy Policy(隐私政策,以下简称 Policy)回答的核心问题是: “这个 App 会如何处理我的(用户的)数据?”它应当描述你处理了哪些类别的数据、数据来源、用途、存放位置与期限、是否以及向谁共享,以及用户如何请求删除。

ChatGPT App 的特殊性在于,用户需要明确知道你究竟从聊天中拿到了什么。OpenAI 特别强调:你的 App 不应尝试还原完整对话,只能处理模型或用户明确发送到工具的片段。这一点也应该在 Policy 中说明。

先不要写文本,而是从架构入手

在动笔写任何法律术语之前,从 SRE/架构师视角审视你的 App:有哪些数据实际会流经系统。

以我们的示例 GiftGenius 为例,可能是这样:

数据类别 来源 存储位置 保留期 / 行为
请求文本(来自聊天的片段) 来自 ChatGPT 的工具调用 后端请求日志 保留 N 天或立刻删除
用户选择的礼物 小部件中的操作 GiftGenius 数据库 保留至账号被删除
用户邮箱(若启用 OAuth) 认证提供方 用户数据库 账号活跃期间
技术指标(IP、时间戳、错误) HTTP 请求 日志 / 监控系统 按日志策略保留 N 天

可以把这样的表直接放进项目文档(例如 /docs):它对开发、安全模块以及 Policy 本身都很有用。

接着把这套结构“翻译”成通俗语言。

GiftGenius 的 Privacy Policy 结构

在教学项目里无需写 20 页长文,简洁但诚实即可。通常可分为以下部分:

  1. 简介:你是谁、这个 App 是什么。
  2. 你收集哪些数据。
  3. 你如何使用这些数据。
  4. 是否以及向谁共享。
  5. 存放位置与保留期限。
  6. 用户权利(包括删除请求)。
  7. 隐私相关的联系方式。

要理解的是,即便是教学项目,这也不是纯模板。你在安全模块里已经思考过日志保留、删除策略、备份——现在需要把这些准确地写出来。

在 Next.js 中最简单的页面实现

我们在应用里创建 /legal/privacy 页面。在 App Router 中这就是一个文件:

// app/legal/privacy/page.tsx
export default function PrivacyPage() {
  return (
    <main className="mx-auto max-w-3xl p-8 prose">
      <h1>Privacy Policy – GiftGenius</h1>
      <p>Last updated: {new Date().toLocaleDateString()}</p>
      {/* 后续是政策章节 */}
    </main>
  );
}

这个示例刻意保持简单:目标是固定一个静态 URL。在真实项目中,政策文本几乎总是单独存放(比如 .md 文件)并被加载进来,避免把大量文本写进 JSX。

例如,可以做一个通用的 loader:

// app/legal/privacy/page.tsx
import policyHtml from "./policy.html"; // 预先构建的 HTML

export default function PrivacyPage() {
  return (
    <main
      className="mx-auto max-w-3xl p-8 prose"
      dangerouslySetInnerHTML={{ __html: policyHtml }}
    />
  );
}

此处值得加一句“不要不明所以地照抄”:dangerouslySetInnerHTML 只有在你可控 HTML 来源(例如由 CI 从 markdown 构建)时才是安全的。

与真实流程对齐

最重要的一点:不要在 Policy 中写你代码里没有的东西。如果你声称:

  • 不会保存请求文本超过 7 天;
  • 可按用户请求彻底删除其资料;
  • 不会使用这些数据来训练你自己的模型,

那么你必须具备:

  • 日志保留期设置;
  • 删除用户的 endpoint 或管理流程;
  • 没有把日志“为了数据科学”导出到外部存储的代码。

反之,如果你启用了使用度量、A/B 实验或按国家的分析,就需要在 Policy 里如实告知,并至少赋予用户基本权利:了解保存了什么,以及请求删除。

数据与 Privacy Policy 搞定后,还需要明确不只是数据处理,而是“游戏规则”本身——这就是 Terms 的任务。

4. Terms of Use / Service:使用规则与 AI 免责声明

为何在已有 Policy 的情况下还需要 Terms

Privacy Policy 回答的是“你如何处理数据”。Terms Of Use/Service(以下简称 Terms)回答的是“在什么条件下可以使用这个 App”。它是你与用户之间的法律协议。

其中会描述:

  • GiftGenius 是什么以及提供哪些功能;
  • 用户哪些行为被视为允许,哪些不允许;
  • AI 的“魔法边界”在哪里(AI 免责声明);
  • 你的责任限制;
  • 争议如何解决以及适用的司法管辖。

对 AI 应用而言,尤其重要的两点是:准确性免责声明与责任限制。

AI 特性:“模型可能会出错”

我们的 GiftGenius 提供礼物推荐。这看起来温和且相对安全,但仍可能踩坑:用户提出“对坚果过敏的人的礼物”,模型生成了不合适的建议,导致用户受伤,大家都不开心。

当然,Terms 并非防弹衣,但它能明确说明:

  • 结果由 AI 生成,可能不准确、过时,甚至离谱;
  • 用户应自行核实重要信息,尤其是与健康、金融和其他敏感领域相关的信息;
  • 你不提供“完美”建议的任何保证,并且对不当使用结果不承担责任。

具体措辞需要最终与法务打磨,但对技术开发者来说,理解这个思路很重要。

与交易相关的细节

如果你的 App 涉及任何支付(关于 ACP 与交易你会在后续模块更深入学习,本课程也已涵盖),就需要在 Terms 中谨慎描述:

  • 通过谁来处理支付(Stripe、ACP 或其他系统);
  • 你能看到哪些支付数据;
  • 退款与取消的条件;
  • 什么被视为成功交易。

平台的一般建议是:明确说明卡片数据由支付服务商处理,而不是你的服务器;你只保存最小必要信息(例如交易 ID)。

在 Next.js 中实现 /legal/terms

技术上与 Privacy Policy 非常类似。创建页面:

// app/legal/terms/page.tsx
export default function TermsPage() {
  return (
    <main className="mx-auto max-w-3xl p-8 prose">
      <h1>Terms of Use – GiftGenius</h1>
      <p>Last updated: {new Date().toLocaleDateString()}</p>
      {/* 章节:服务描述、限制、AI 免责声明、责任 */}
    </main>
  );
}

与 Policy 一样,最好把正文放在单独文件或 CMS 中,而在代码里只保留最小的标记。

可以抽出法律页面的通用布局:

// app/legal/LegalLayout.tsx
export function LegalLayout(props: { title: string; children: React.ReactNode }) {
  return (
    <main className="mx-auto max-w-3xl p-8 prose">
      <h1>{props.title}</h1>
      <p>Last updated: {new Date().toLocaleDateString()}</p>
      {props.children}
    </main>
  );
}

随后同时用于 Policy 和 Terms。这不是“代码美化”,而是为了避免忘记更新时间并保持统一风格。

5. Support / Contact:用户遇到问题该去哪里

最低要求与“体面做法”

OpenAI 的指南要求 App 必须提供清晰的方式联系开发者以获取支持。可以只是一个 email,但它必须真实可用,能接收邮件并有人回复。

教学项目的最小化选项:

  • 单独的 /support 页面,简短说明并提供 mailto:support@yourdomain.com

更成熟的做法:

  • 反馈表单;
  • 文档或帮助中心链接;
  • 如果你在打造产品社区,可能还会有 Slack/Discord 链接。

Next.js 中的 /support 页面

先看一个非常简单的版本:

// app/support/page.tsx
export default function SupportPage() {
  return (
    <main className="mx-auto max-w-xl p-8 prose">
      <h1>GiftGenius Support</h1>
      <p>
        If you have issues or questions, email us at{" "}
        <a href="mailto:support@giftgenius.app">support@giftgenius.app</a>.
      </p>
    </main>
  );
}

稍微进阶一点,可以加一个简单表单:

// app/support/page.tsx
"use client";

export default function SupportPage() {
  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    // 这里将调用 API 来发送邮件/工单
  };

  return (
    <main className="mx-auto max-w-xl p-8 prose">
      <h1>GiftGenius Support</h1>
      <form onSubmit={handleSubmit}>
        <input name="email" placeholder="Your email" className="border p-2 w-full" />
        <textarea name="message" placeholder="How can we help?" className="border p-2 w-full mt-2" />
        <button type="submit" className="mt-4 px-4 py-2 border rounded">
          Send
        </button>
      </form>
    </main>
  );
}

即使你在教学项目中没有真正实现该表单的后端,只要提供清晰的 URL 和页面结构,就已更接近 Store 的要求。

与事故管理的关联

Support 页面不仅是“系统挂了去哪儿报修”,也是你运维图景的一部分。在后续模块中我们会讨论事故与 App 的日常运维。届时 Support 页面会成为用户的“入口”:通过它提交 bug 报告、问题咨询、数据删除请求。此刻,至少要确保这扇门存在,并且不会通向“404 Not Found”。

6. 将法律页面集成到应用与列表中

在项目内统一配置 URL

为了避免在代码中四处散落“魔法字符串”,可以建立一个简单的配置:

// lib/appConfig.ts
export const legalLinks = {
  privacy: "https://giftgenius.app/legal/privacy",
  terms: "https://giftgenius.app/legal/terms",
  support: "https://giftgenius.app/support",
} as const;

你会在以下位置使用这些 URL:

  • ChatGPT App 的设置(元数据);
  • 产品的落地页;
  • 邮件中(如果你实现了 email 通知)。

在小部件内部,你可以通过 openExternal 为用户提供快速访问这些页面的能力。

// 在 GiftGenius 的 React 小部件内
import { legalLinks } from "../lib/appConfig";

function FooterLinks() {
  const handleOpen = (url: string) => {
    window.openai?.openExternal({ url }); // Apps SDK helper
  };

  return (
    <footer className="mt-4 text-xs text-gray-500">
      <button onClick={() => handleOpen(legalLinks.privacy)}>Privacy</button>
      <span> · </span>
      <button onClick={() => handleOpen(legalLinks.terms)}>Terms</button>
    </footer>
  );
}

在真实的小部件代码中,最好使用 Apps SDK 的 useOpenExternal 钩子;此处为简洁起见展示了通过 window.openai 的直接调用。

这样可以提高透明度:用户可在小部件内一键打开法律文档,而不必在 Store 里寻找。

用户与审核员的流程

用一个小图看看交互流程:

flowchart TD
  A[ChatGPT Store 列表页] --> B[用户阅读 App 描述]
  B --> C[通过链接打开 Privacy / Terms]
  B --> D[安装/开始使用 App]
  D --> E[启动 GiftGenius 小部件]
  E --> F["如有需要点击 'Support' 或 'Privacy'"]

ChatGPT Store 的审核员大致也会按类似路径,但会更挑剔。他会查看:

  • 列表页里写了什么;
  • Policy 与 Terms 承诺了什么;
  • App 在真实场景中的行为;
  • 行为是否与文档描述一致。

如果一切如实且可预期——通过审核的概率会显著提高。

7. 你的 App 的实操练习

不要停留在理论层面,最好现在就为你的应用起草文档。

建议做法如下。

先在架构层面描述:

  • 你处理哪些数据类别(请求文本、订单、邮箱、指标);
  • 是否保存文本请求,若保存,保留多久;
  • 接入了哪些外部服务(托管、数据库、支付、分析)。

之后:

  1. 拟定 Privacy Policy 的结构,包括“收集什么”“用途”“是否/向谁共享”“保存多久”“如何删除数据”。
  2. 拟定 Terms 的结构:服务描述、使用规则、限制(禁止内容与滥用)、AI 免责声明、责任限制、指向 Policy 的链接。
  3. 做一个 /support 页面,包含简短文本与 email。
  4. 在项目中添加 lib/appConfig.ts,配置法律页面 URL,并在小部件及所有外部链接中使用。

即便文本只是草稿、计划“以后给律师看看”,你也已经完成了重要工作:把技术实现与法律描述关联起来。

8. 准备法律页面时的常见错误

错误 №1:从网上随便抄一份隐私政策且不做修改。
有时会想直接拿到一份现成隐私政策,替换产品名就收工。问题是,这样的文本几乎肯定与你的架构不匹配。它可能包含移动应用、推送通知、某些特定分析服务等你并未使用的内容,反之也可能完全没有提到 MCP 服务器、工具日志、通过 ChatGPT 的工作流。审核员会注意到这些不一致,而用户也会感觉“这不是写给这个产品的”。

错误 №2:在 Policy 中承诺了代码里没有实现的事情。
经典例子是“我们会在收到请求后删除你的所有数据”,但代码里既没有删除的 endpoint,也没有定位某个用户数据的机制。类似的还有日志保留期,以及“我们不保存你的消息文本”的表述,若你实际上把 tool‑input 存进了没有保留期的日志系统。这种不一致对审核和真实用户都很危险。

错误 №3:在 Terms 中忽略 AI 特性。
如果 Terms 完全没有说明答案由模型生成且可能不准确,用户就可能把你的 App 当成“绝对真理”。对推荐类服务(礼物、旅行、商品)还勉强能容忍,但在医疗、金融或法律建议上,缺失可能带来严重后果。最好明确、诚实地说明限制与责任。

错误 №4:Support 页面没有真实联系方式或邮箱长期无人处理。
/support 页面指向 mailto:hello@example.com,却从没人查看,这样虽然形式上存在,实际却毫无用处。用户得不到反馈,Bug 报告丢失,App 的口碑也会受损。平台同样期望你回应投诉与问题。即便是小团队,也应至少每隔几天查看收件箱并作出回应。

错误 №5:忘记标注文档的日期与版本。
法律页面上有时完全没有更新时间。对审核员来说,这是个警讯:无法判断文档是否与当前产品状态一致。一个简单的“Last updated: …”区块就能解决问题,对用户与你都更友好,并且在你随着架构演进而更新 Policy/Terms 时,利于维护变更历史。

评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION