CodeGym /Các khóa học /ChatGPT Apps /Privacy Policy, Terms, Support: các trang pháp lý bắt buộ...

Privacy Policy, Terms, Support: các trang pháp lý bắt buộc

ChatGPT Apps
Mức độ , Bài học
Có sẵn

1. Vì sao cần có Privacy Policy, Terms và Support

Bắt đầu với một sự thật không mấy dễ chịu: với ChatGPT Store, việc có chính sách quyền riêng tư công khai và thông tin liên hệ hỗ trợ — không phải “phép lịch sự”, mà là yêu cầu bắt buộc. Trong hướng dẫn của OpenAI nêu rõ rằng mỗi App phải có Privacy Policy được công bố, trong đó giải thích rõ thu thập dữ liệu nào và sử dụng ra sao, đồng thời cung cấp thông tin liên hệ hỗ trợ.

Nhưng câu chuyện không chỉ để “cho moderator bớt soi”. Những tài liệu này giải quyết đồng thời nhiều mục tiêu.

Thứ nhất, đây là mức độ tin cậy tối thiểu đối với người dùng. Họ thấy đằng sau ứng dụng là con người hoặc công ty thật, có luật chơi rõ ràng và có nơi để liên hệ khi gặp vấn đề. Trong một thế giới nơi “dịch vụ AI tiếp theo” xuất hiện mỗi ngày, điều này đã là lợi thế cạnh tranh.

Thứ hai, đây là sự “pháp điển hoá” những gì bạn đã làm trong kiến trúc. Mọi thứ bạn quyết định trong các mô-đun về bảo mật, ghi log, thời hạn lưu trữ, xoá dữ liệu và xử lý thanh toán phải được phản ánh bằng lời. Nếu bạn hứa “không lưu cuộc hội thoại”, nhưng lại ghi log toàn bộ tool‑input mãi mãi, thì đó không chỉ là thiếu đẹp — mà còn là lý do cho các khiếu nại nghiêm trọng.

Thứ ba, đây là một lớp “hợp đồng” nữa giữa bạn và OpenAI. Store thực chất nói: “Chúng tôi sẵn sàng hiển thị App của bạn cho hàng triệu người, nhưng bạn phải mô tả trung thực bạn làm gì với họ và luôn sẵn sàng liên lạc khi có vấn đề.”

Tóm lại: các trang pháp lý không phải chuyện “luật sư ép buộc”. Đó là cách đồng bộ kỳ vọng: App làm gì, chạm vào dữ liệu nào, bạn sẵn sàng chịu trách nhiệm đến đâu, và người dùng có thể liên hệ với bạn bằng cách nào.

2. Các URL pháp lý này ở đâu trong ChatGPT App

Về mặt kỹ thuật, với ChatGPT App, các trang pháp lý là các URL công khai bình thường mà bạn khai báo trong metadata của ứng dụng và trong listing trên Store. Trong hướng dẫn chúng thường được gọi là privacy_policy_url, terms_of_service_url và liên hệ hỗ trợ.

Các URL này cần đáp ứng vài điều kiện đơn giản nhưng quan trọng:

  1. Chúng sống trên tên miền ổn định của sản phẩm hoặc công ty bạn. Không dùng ngrok tạm thời, nếu không sau một tuần Store sẽ dẫn người dùng đến hư không.
  2. Chúng truy cập được mà không cần đăng nhập. Người dùng (và reviewer) phải mở được trong trình duyệt mà không cần đăng nhập hay nghi thức rườm rà.
  3. Chúng cập nhật và khớp với thực tế. Nếu bạn thay đổi kiến trúc xử lý dữ liệu, theo thời gian cũng cần cập nhật văn bản.

Trong dự án học tập GiftGenius của chúng ta đã có frontend trên Next.js, triển khai, ví dụ, trên Vercel. Vậy nơi hợp lý cho các trang pháp lý là các route dạng:

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

Về bản chất đây chỉ là thêm ba trang nữa trong ứng dụng, nhưng chính những trang này bạn sẽ dán vào form gửi App đi review.

3. Privacy Policy: mô tả trung thực bạn làm gì với dữ liệu

Vai trò của Privacy Policy

Privacy Policy (chính sách quyền riêng tư, sau đây gọi tắt là Policy) trả lời câu hỏi chính: “App này làm gì với dữ liệu của tôi (người dùng)?” Nó phải mô tả bạn xử lý những loại dữ liệu nào, chúng đến từ đâu, cần để làm gì, lưu ở đâu và trong bao lâu, chia sẻ cho ai và người dùng có thể yêu cầu xoá bằng cách nào.

Đặc thù của ChatGPT Apps là người dùng cần hiểu chính xác bạn nhận được gì từ cuộc chat. OpenAI nhấn mạnh: App của bạn không nên cố khôi phục toàn bộ cuộc hội thoại, mà chỉ làm việc với những phần được mô hình hoặc người dùng gửi rõ ràng vào công cụ. Điều này cũng nên được nêu trong Policy.

Bắt đầu không phải từ chữ, mà từ kiến trúc

Trước khi viết bất kỳ câu chữ pháp lý nào, hãy nhìn App của bạn bằng con mắt của SRE/kiến trúc sư: dữ liệu nào thật sự đi qua hệ thống.

Với ví dụ GiftGenius, có thể như sau:

Hạng mục dữ liệu Nguồn Nơi lưu trữ Thời hạn / hành vi
Văn bản yêu cầu (đoạn trích từ chat) Lời gọi tool từ ChatGPT Log yêu cầu ở backend N ngày hoặc xoá ngay
Quà tặng người dùng đã chọn Hành động trong widget CSDL GiftGenius Lưu cho tới khi xoá tài khoản
Email người dùng (nếu có OAuth) Nhà cung cấp xác thực CSDL người dùng Chừng nào tài khoản còn hoạt động
Chỉ số kỹ thuật (IP, timestamp, lỗi) Yêu cầu HTTP Log / hệ thống giám sát N ngày theo chính sách log

Bạn có thể đưa một bảng như vậy ngay trong tài liệu dự án (ví dụ ở /docs): nó hữu ích cho phát triển, cho mô-đun bảo mật, và cho chính Policy.

Sau đó “dịch” cấu trúc này sang ngôn ngữ gần gũi, dễ hiểu.

Cấu trúc Privacy Policy cho GiftGenius

Trong dự án học tập, không cần viết một thiên anh hùng ca 20 trang; một cấu trúc gọn gàng nhưng trung thực là đủ. Thường có các phần:

  1. Mở đầu: bạn là ai và App là gì.
  2. Bạn thu thập dữ liệu nào.
  3. Bạn sử dụng dữ liệu ra sao.
  4. Bạn chia sẻ cho ai.
  5. Bạn lưu ở đâu và bao lâu.
  6. Quyền của người dùng (bao gồm yêu cầu xoá).
  7. Liên hệ về quyền riêng tư.

Cần hiểu rằng ngay cả với dự án học tập, đây không phải là “mẫu cho có”. Ở mô-đun bảo mật bạn đã cân nhắc thời hạn lưu log, chính sách xoá, backup — giờ cần diễn đạt cẩn thận những điều đó.

Triển khai đơn giản nhất trong Next.js

Hãy tạo trang /legal/privacy trong ứng dụng. Với App Router, đây đúng nghĩa là một file:

// 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>
      {/* các phần của chính sách ở bên dưới */}
    </main>
  );
}

Ví dụ này cố tình tối giản: mục tiêu là cố định URL tĩnh. Trong dự án thực tế, nội dung chính sách gần như luôn được lưu riêng (ví dụ trong file .md) và được nạp vào, tránh để hàng đống chữ trong JSX.

Ví dụ, có thể làm một loader điển hình:

// app/legal/privacy/page.tsx
import policyHtml from "./policy.html"; // HTML đã build sẵn

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

Một ghi chú kiểu “đừng bắt chước nếu chưa hiểu” hoàn toàn phù hợp ở đây: dangerouslySetInnerHTML chỉ an toàn khi bạn kiểm soát nguồn HTML (ví dụ tự build từ markdown trong CI).

Liên kết với quy trình thực tế

Điều quan trọng nhất: đừng viết trong Policy điều bạn không có trong code. Nếu bạn tuyên bố rằng:

  • không lưu văn bản yêu cầu quá 7 ngày;
  • xóa hoàn toàn hồ sơ người dùng khi họ yêu cầu;
  • không dùng dữ liệu đó để huấn luyện mô hình của riêng bạn,

thì bạn phải có:

  • thiết lập thời hạn lưu (retention) trong log;
  • endpoint hoặc quy trình admin để xoá người dùng;
  • không có đoạn code nào đẩy log sang kho lưu trữ bên ngoài “cho Data Science”.

Và ngược lại: nếu bạn bật chỉ số sử dụng, thử nghiệm A/B hoặc phân tích theo quốc gia, hãy nêu trung thực trong Policy. Đồng thời cho người dùng các quyền cơ bản: biết dữ liệu nào được lưu và yêu cầu xoá.

Xong phần dữ liệu và Privacy Policy. Giờ cần cố định không chỉ xử lý dữ liệu mà cả “luật chơi” — đó là nhiệm vụ của Terms.

4. Terms of Use / Service: luật chơi và AI disclaimer

Tại sao cần Terms khi đã có Policy

Privacy Policy trả lời câu hỏi “bạn làm gì với dữ liệu”. Terms Of Use/Service (sau đây gọi là Terms) — trả lời “người dùng được phép sử dụng App với những điều kiện nào”. Đây là hợp đồng pháp lý giữa bạn và người dùng.

Trong đó mô tả:

  • GiftGenius là gì và cung cấp chức năng nào;
  • hành vi nào của người dùng là chấp nhận được, hành vi nào thì không;
  • “ranh giới phép màu” của AI (AI disclaimer);
  • các giới hạn trách nhiệm của bạn;
  • cách giải quyết tranh chấp và thẩm quyền tài phán.

Với ứng dụng AI, đặc biệt quan trọng có hai điểm: tuyên bố về độ chính xác và giới hạn trách nhiệm.

Đặc thù AI: “mô hình có thể sai”

GiftGenius đưa ra gợi ý quà tặng. Điều này dễ thương và tương đối an toàn, nhưng ngay cả vậy cũng có thể gặp rủi ro: người dùng yêu cầu “quà cho người dị ứng hạt”, mô hình sinh ra gợi ý không phù hợp, người đó gặp vấn đề, ai cũng khổ.

Dĩ nhiên Terms không phải áo giáp chống mọi rủi ro, nhưng chúng xác lập rõ ràng:

  • kết quả do AI sinh ra và có thể không chính xác, lỗi thời hoặc kỳ quặc;
  • người dùng phải tự kiểm tra lại thông tin quan trọng, đặc biệt liên quan đến sức khoẻ, tài chính và các lĩnh vực nhạy cảm khác;
  • bạn không đưa ra bất kỳ bảo đảm nào về “độ hoàn hảo” của gợi ý và không chịu trách nhiệm khi kết quả bị sử dụng sai mục đích.

Các câu chữ cụ thể cần được chỉnh sửa cùng luật sư, nhưng với kỹ sư, điều quan trọng là hiểu tinh thần này.

Các lưu ý về thương mại (commerce)

Nếu App của bạn có bất kỳ hành vi thanh toán nào (mô-đun về ACP và commerce sẽ được học kỹ hơn sau), trong Terms cần mô tả cẩn thận:

  • thanh toán đi qua đâu (Stripe, ACP, hệ thống khác);
  • bạn thực sự nhìn thấy dữ liệu thanh toán nào;
  • điều kiện hoàn tiền và hủy đơn;
  • thế nào được tính là giao dịch thành công.

Khuyến nghị chung từ nền tảng — nêu rõ dữ liệu thẻ do nhà cung cấp thanh toán xử lý, không phải server của bạn, và bạn chỉ lưu tối thiểu (ví dụ, ID giao dịch).

Triển khai /legal/terms trong Next.js

Về kỹ thuật rất giống Privacy Policy. Tạo trang:

// 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>
      {/* các mục: mô tả dịch vụ, giới hạn, AI disclaimer, trách nhiệm */}
    </main>
  );
}

Và cũng như với Policy, tốt hơn là giữ nội dung trong file riêng hoặc CMS, còn trong code chỉ có phần khung tối thiểu.

Có thể trích xuất một layout chung cho các trang pháp lý:

// 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>
  );
}

Sau đó dùng lại cho cả Policy và Terms. Đây không chỉ là “đẹp code”, mà còn giúp bạn không quên đặt ngày cập nhật và giữ phong cách thống nhất.

5. Support / Contact: người dùng liên hệ ở đâu khi gặp vấn đề

Tối thiểu và “thực hành tốt”

Hướng dẫn của OpenAI nêu rằng App phải có cách rõ ràng để liên hệ nhà phát triển cho mục đích hỗ trợ. Có thể chỉ là một email đơn giản, nhưng email đó phải tồn tại, nhận thư và thỉnh thoảng có phản hồi.

Phương án tối thiểu cho dự án học tập:

  • một trang riêng /support với mô tả ngắn và mailto:support@yourdomain.com.

Phương án “trưởng thành” hơn:

  • form liên hệ;
  • đường dẫn tới tài liệu hoặc Help Center;
  • có thể thêm liên kết Slack/Discord nếu bạn xây dựng cộng đồng quanh sản phẩm.

Trang /support trong Next.js

Bắt đầu từ biến thể thật đơn giản:

// 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>
  );
}

Hơi nâng cao hơn — thêm một form đơn giản:

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

export default function SupportPage() {
  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    // ở đây sẽ gọi API để gửi email/ticket
  };

  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>
  );
}

Ngay cả khi bạn chưa triển khai backend thật cho form này trong dự án học tập, chỉ riêng việc có URL rõ ràng và cấu trúc trang phù hợp đã giúp bạn tiến gần hơn tới yêu cầu của Store.

Liên hệ với incident management

Trang Support không chỉ là “nơi viết khi mọi thứ sập”, mà còn là một phần bức tranh vận hành của bạn. Ở các mô-đun sau, bạn sẽ nói về sự cố và cuộc sống vận hành của App. Khi đó, trang Support sẽ là “cửa vào” cho người dùng: qua đó họ gửi báo cáo bug, câu hỏi, yêu cầu xoá dữ liệu. Hiện tại, điều quan trọng là ít nhất hãy cố định rằng cánh cửa đó tồn tại và không dẫn tới “404 Not Found”.

6. Tích hợp các trang pháp lý vào ứng dụng và listing

Cấu hình URL thống nhất trong dự án

Để không rải rác các “chuỗi ma thuật” URL trong code, bạn có thể tạo một cấu hình đơn giản:

// 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;

Các URL này bạn sẽ dùng ở:

  • cài đặt ChatGPT App (metadata);
  • trang landing của sản phẩm;
  • email, nếu bạn triển khai thông báo qua email.

Bên trong widget, bạn có thể cung cấp lối tắt đến những trang này thông qua openExternal.

// bên trong React widget GiftGenius
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>
  );
}

Trong code widget thực tế, tốt hơn hãy dùng hook useOpenExternal từ Apps SDK; ở đây để ngắn gọn, ta minh hoạ bằng lời gọi trực tiếp qua window.openai.

Như vậy bạn tăng tính minh bạch: từ widget người dùng có thể mở tài liệu pháp lý chỉ bằng một cú click, thay vì phải tìm ở đâu đó trong Store.

Luồng người dùng và reviewer

Xem luồng tương tác trong sơ đồ nhỏ sau:

flowchart TD
  A[Trang listing trong ChatGPT Store] --> B[Người dùng đọc mô tả App]
  B --> C[Mở Privacy / Terms theo liên kết]
  B --> D[Cài đặt / bắt đầu dùng App]
  D --> E[Khởi chạy widget GiftGenius]
  E --> F["Khi cần thì bấm 'Support' hoặc 'Privacy'"]

Reviewer của ChatGPT Store đi theo luồng gần như vậy, chỉ là kỹ tính hơn. Họ xem:

  • những gì được viết trong listing;
  • những gì Policy và Terms cam kết;
  • App hành xử thế nào trong kịch bản thực tế;
  • hành vi có khớp với những gì bạn đã viết hay không.

Nếu mọi thứ trung thực và có thể dự đoán — cơ hội vượt qua review tăng mạnh.

7. Bài tập thực hành cho App của bạn

Đừng chỉ dừng ở lý thuyết, hãy phác thảo ngay các bản nháp tài liệu cho ứng dụng của bạn.

Cách làm có thể như sau.

Đầu tiên, ở mức kiến trúc hãy mô tả:

  • bạn xử lý những loại dữ liệu nào (văn bản yêu cầu, đơn hàng, email, chỉ số);
  • bạn có lưu văn bản yêu cầu không, nếu có thì bao lâu;
  • những dịch vụ bên ngoài nào được tích hợp (hosting, CSDL, thanh toán, phân tích).

Sau đó:

  1. Xây dựng cấu trúc Privacy Policy với các phần “thu thập gì”, “vì sao”, “chia sẻ cho đâu”, “lưu bao lâu”, “xoá dữ liệu thế nào”.
  2. Xây dựng cấu trúc Terms: mô tả dịch vụ, quy tắc sử dụng, hạn chế (nội dung bị cấm và lạm dụng), AI disclaimer, giới hạn trách nhiệm, liên kết tới Policy.
  3. Tạo trang /support với đoạn mô tả ngắn và email.
  4. Thêm vào dự án lib/appConfig.ts với các URL pháp lý và dùng chúng trong widget cũng như mọi liên kết bên ngoài.

Dù các văn bản còn rất nháp và bạn dự định “sau này đưa luật sư xem lại”, thì bạn đã làm được điều quan trọng: liên kết triển khai kỹ thuật với mô tả pháp lý.

8. Các lỗi thường gặp khi chuẩn bị trang pháp lý

Lỗi #1: sao chép ngẫu nhiên một chính sách quyền riêng tư trên mạng và không chỉnh sửa.
Đôi khi chỉ muốn lấy đại một chính sách, thay tên sản phẩm là xong việc. Vấn đề là văn bản đó gần như chắc chắn không khớp kiến trúc của bạn. Có thể có phần nói về ứng dụng di động, push notification hoặc một số dịch vụ phân tích cụ thể mà bạn không dùng, và ngược lại — chẳng nói gì về máy chủ MCP, log của công cụ và cách hoạt động qua ChatGPT. Reviewer sẽ nhận ra sự lệch pha, còn người dùng sẽ cảm thấy văn bản “viết cho ai đó khác”.

Lỗi #2: hứa hẹn trong Policy những điều chưa có trong code.
Ví dụ kinh điển — câu “chúng tôi xoá mọi dữ liệu của bạn ngay khi có yêu cầu”, trong khi code không có endpoint xoá, thậm chí không có cơ chế tìm dữ liệu theo người dùng. Tương tự với thời hạn lưu log và câu “chúng tôi không lưu văn bản tin nhắn của bạn”, nếu thực tế bạn đẩy tool‑input vào hệ thống log không có retention. Sự bất nhất này nguy hiểm cho cả review lẫn người dùng thật.

Lỗi #3: bỏ qua đặc thù AI trong Terms.
Nếu trong Terms không có câu nào nêu rằng câu trả lời do mô hình sinh ra và có thể không chính xác, người dùng có thể kỳ vọng App của bạn ở mức “chân lý tuyệt đối”. Với dịch vụ gợi ý (quà tặng, du lịch, chọn hàng) điều này còn tạm chấp nhận, nhưng trong y tế, tài chính hoặc tư vấn pháp lý, lỗ hổng này có thể kết thúc rất tệ. Hãy nói rõ và trung thực về giới hạn và trách nhiệm.

Lỗi #4: trang Support không có liên hệ thật hoặc dùng địa chỉ “chết”.
Trang /support dẫn tới mailto:hello@example.com mà không ai kiểm tra bao giờ thì tồn tại trên giấy, nhưng vô dụng trên thực tế. Người dùng không nhận được phản hồi, báo cáo lỗi bị thất lạc, danh tiếng App đi xuống. Nền tảng cũng kỳ vọng bạn phản hồi khiếu nại và vấn đề. Dù bạn là đội nhỏ, hãy xem hộp thư vài ngày một lần và phản hồi.

Lỗi #5: quên ngày và phiên bản tài liệu.
Đôi khi trên trang pháp lý không có chỉ dấu nào về lần cập nhật gần nhất. Với reviewer, đó là tín hiệu đáng lo: không rõ tài liệu có phản ánh trạng thái hiện tại của sản phẩm hay không. Một block đơn giản “Last updated: …” giải quyết vấn đề cho cả bạn và người dùng, đồng thời giúp theo dõi lịch sử thay đổi khi theo thời gian bạn chỉnh sửa kiến trúc và, tương ứng, nội dung Policy/Terms.

Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION