CodeGym /Các khóa học /ChatGPT Apps /Tích hợp Product Feed, Merchant và ACP trong một dự án

Tích hợp Product Feed, Merchant và ACP trong một dự án

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

1. Mọi thứ đã hoạt động riêng lẻ…

Tới thời điểm này, bạn đã hình dung commerce‑flow xoay quanh ChatGPT như thế nào. Merchant có product feed, các ACP‑endpoint (/checkout_sessions và đồng bọn) đã được triển khai, Instant Checkout thực hiện thanh toán, còn backend nhận webhooks và tạo đơn hàng. Tất cả điều này có thể chạy ngay cả khi không có ChatGPT App của bạn: chỉ cần Product Feed + ACP-backend.

Bạn đã biết làm riêng lẻ:

  • xây Product Feed theo đặc tả của OpenAI;
  • thiết kế và triển khai Agentic Checkout / Delegated Payment;
  • viết ChatGPT App với widget và các MCP‑tool để tìm quà tặng.

Nhìn riêng lẻ thì rất đẹp, nhưng ghép lại dễ biến thành “vườn thú dịch vụ”. Widget sống cuộc đời của nó, máy chủ MCP — cuộc đời của nó, ACP‑backend là một cuộc đời nữa, còn logic đơn hàng và webhook — cuộc đời thứ tư. Ngay lần đầu debug một giao dịch thật hoặc sửa một bug kỳ lạ, bạn chợt hiểu rằng chẳng ai nhìn thấy bức tranh tổng thể.

Mục tiêu của bài giảng này — kéo bạn ra khỏi trạng thái đó và đưa ra một kiến trúc vừa toàn diện vừa khả thi: chính xác Product Feed gắn với ACP‑backend thế nào, cả hai liên hệ ra sao với ChatGPT App và widget, vị trí xuất hiện của nhà cung cấp thanh toán, và tất cả được gói lại thành các thành phần dễ hiểu cho đội: service, CSDL, API.

Đồng thời, chúng ta sẽ liên tục nhấn mạnh: đâu là SPEC tiêu chuẩn cứng, còn đâu chỉ là lựa chọn kiến trúc của chúng ta cho GiftGenius.

Insight: ChatGPT là Google miễn phí

ChatGPT làm việc với người dùng gần giống Google: nó miễn phí mang đến cho bạn traffic phù hợp, vì nó kiếm tiền ở chỗ khác — từ chính người dùng.

Về mặt kinh doanh, điều này có nghĩa đơn giản: ChatGPT trở thành “kênh quảng cáo” miễn phí cho hàng hóa của bạn, với điều kiện bạn đã bật Product Feed và ACP-backend. Mô hình sẽ đề xuất sản phẩm của bạn nếu chúng khớp nhu cầu người dùng, và bạn không cần trả riêng cho lượt hiển thị hay click.

Từ đó có hai kết luận thực tiễn:

  1. Cửa sổ cơ hội TẠM THỜI rất rẻ. Hiện cạnh tranh trong hệ sinh thái ACP còn thấp, và bạn có thể chạm phân khúc giá cao mà không cần ngân sách quảng cáo quen thuộc. Đây là tình huống hiếm khi traffic với tỉ lệ chuyển đổi cao cho sản phẩm đắt (hàng không, bất động sản, hàng premium, bảo hiểm) có thể gần như miễn phí.
  2. Nên bắt đầu từ các vertical có biên lợi nhuận cao. Nếu bạn có quyền truy cập các danh mục có giá trị đơn cao, hợp lý nhất là kết nối chúng trước:
    • bán/cho thuê máy bay, du thuyền, biệt thự;
    • bán/cho thuê nhà và bất động sản cao cấp;
    • trang sức, đồng hồ đắt tiền, sản phẩm và dịch vụ bảo hiểm.

Điều này không đảm bảo “triệu đô nhanh”, nhưng tạo bất đối xứng: ai sớm dựng được Product Feed chất lượng và ACP‑backend đáng tin trong phân khúc đắt sẽ nhận mức lợi ích vượt trội từ kênh này, khi nó còn bị đánh giá thấp và gần như miễn phí.

2. Kiến trúc tham chiếu GiftGenius: cái nhìn tổng quan

Bắt đầu từ góc nhìn trên cao. Nhớ lại bức tranh chung từ các mô-đun trước: người dùng nhắn trong ChatGPT, mô hình gọi công cụ của bạn, còn lớp commerce sống ở một backend riêng.

Xác định các khối chính của GiftGenius.

Thứ nhất, ChatGPT UI và mô hình GPT, dẫn dắt hội thoại với người dùng và khi cần thì gọi GiftGenius‑App (hoặc thậm chí hoạt động không cần App — chỉ dựa vào Product Feed).

Thứ hai, widget GiftGenius (Next.js + Apps SDK), hiển thị thẻ quà tặng và khi cần thì tiến trình checkout. Nó sống trong sandbox window.openai và không biết gì về thông tin thanh toán thực.

Thứ ba, lớp MCP, cung cấp cho mô hình các công cụ để tìm quà theo catalog (Product Feed) và có thể đọc lịch sử đơn hàng.

Thứ tư, commerce / ACP‑backend, nơi:

  • đọc Product Feed như nguồn chân lý về sản phẩm và SKU;
  • triển khai Agentic Checkout Spec (/checkout_sessions, webhooks, trạng thái);
  • giao tiếp với nhà cung cấp thanh toán (ví dụ, Stripe) theo Delegated Payment Spec.

Thứ năm, các cơ sở dữ liệu về catalog (nếu feed sinh ra từ CSDL), đơn hàng và cấu trúc phụ trợ (người dùng, cấu hình).

Cuối cùng, nhà cung cấp thanh toán, nơi lưu trữ và xử lý dữ liệu thanh toán, đồng thời gửi webhooks về kết quả thanh toán.

Sơ đồ có thể vẽ như sau:

graph LR
  U[Người dùng trong ChatGPT] --> GPT[Mô hình GPT]
  GPT -->|render| W[GiftGenius Widget
Next.js + Apps SDK] GPT -->|công cụ MCP| MCP[Máy chủ MCP
tìm quà tặng] MCP --> PF["Product Feed
(CSDL/JSON)"] GPT -->|ACP HTTP| ACP[GiftGenius Commerce Backend
Agentic Checkout] ACP --> ORDERS[Cơ sở dữ liệu đơn hàng] ACP --> PSP["Nhà cung cấp thanh toán
(Stripe, v.v.)"] PSP --> ACP ACP -->|webhooks/sự kiện| GPT

Sơ đồ này mô tả kiến trúc GiftGenius như một ví dụ triển khai. Định dạng Product Feed, hợp đồng /checkout_sessions và giao thức Delegated Payment là phần thuộc chuẩn ACP; vị trí dịch vụ, lược đồ CSDL và tách tiến trình là lựa chọn kiến trúc của bạn.

3. Product Feed, ACP và widget liên kết logic thế nào

Để không lạc trong mớ mũi tên, ghi nhớ một ý tưởng đơn giản nhưng cốt lõi: bạn có đúng một nguồn chân lý về sản phẩm.

Trong thế giới GiftGenius, giả sử đó là bảng products + skus trong PostgreSQL. Từ đây bạn sẽ:

  1. Tạo Product Feed theo đặc tả OpenAI (trực tiếp hoặc qua xuất liệu).
  2. Xây chỉ mục tìm kiếm cho MCP‑tool (ví dụ, search_gifts).
  3. Thực hiện xác thực cho yêu cầu từ ACP‑backend — kiểm tra sku_id có tồn tại và có giá/đơn vị tiền tệ hợp lệ hay không.

Như vậy, MCP‑search và ACP‑checkout cùng nhìn về một nguồn dữ liệu, còn widget chỉ hiển thị kết quả đến từ MCP‑tool hoặc gián tiếp từ ACP (ví dụ, thông tin đơn hàng).

Bạn có thể hình dung đây là hai “cửa sổ” nhìn vào cùng một catalog: một cửa sổ cho tìm kiếm/khuyến nghị, cửa sổ kia cho đặt mua. Nếu chúng nhìn vào hai CSDL khác nhau, bạn sẽ sớm gặp những sai lệch vui nhộn.

4. Mô hình dữ liệu: từ Product Feed đến đơn hàng

Bắt đầu với các kiểu TypeScript đơn giản, sẽ sống trong repo GiftGenius của bạn (ví dụ, trong src/domain/commerce.ts). Các kiểu này không phải bản sao y nguyên của đặc tả, nhưng phản ánh các ý chính theo dạng tiện dùng cho ứng dụng.

// src/domain/commerce.ts

export interface ProductSku {
  id: string;          // SKU ID ổn định (trùng với Product Feed)
  title: string;       // tên dễ đọc cho con người
  priceCents: number;  // giá theo cent/đơn vị nhỏ
  currency: string;    // mã ISO, ví dụ "usd"
}

export type CheckoutStatus = "pending" | "succeeded" | "failed";

export interface CheckoutSession {
  id: string;
  skuId: string;
  totalCents: number;
  currency: string;
  status: CheckoutStatus;
}

Ở đây, chúng ta ghi rõ vào CheckoutSession tham chiếu tới skuId và đơn vị tiền/giá cố định. Đây là mô hình nội bộ; Agentic Checkout Spec thực tế phong phú hơn, nhưng ý tưởng cơ bản tương tự: session — “mua cái gì, bao nhiêu và đang ở trạng thái nào”.

Tiếp theo là kiểu đơn hàng:

export interface Order {
  id: string;
  userId: string;
  skuId: string;
  totalCents: number;
  currency: string;
  checkoutSessionId: string;
  status: "awaiting_payment" | "paid" | "canceled" | "refunded";
}

Ở đây có ảnh hưởng từ các thực thể chung ở mô-đun trước: intent, checkout_session, order. Trong dự án học tập, chúng ta gộp nhẹ intent và order để tránh sinh thêm thực thể, nhưng vẫn giữ liên kết tới checkoutSessionId.

5. Cách widget GiftGenius “nhìn lén” vào thế giới commerce

Điểm quan trọng: bản thân widget không gọi thẳng nhà cung cấp thanh toán và thậm chí không cần biết chi tiết ACP; vai trò của nó — hiển thị cho người dùng trạng thái đã được tính toán và ghi nhận ở backend.

Kịch bản đơn giản, hữu ích: sau khi mua thành công, người dùng quay lại chat và hỏi “Hiển thị các đơn gần đây của tôi trong GiftGenius”. GPT sẽ gọi MCP‑tool như get_user_orders, tool này gọi backend của bạn, và widget sẽ hiển thị danh sách.

Hình dung một route API của Next.js trả về các đơn gần đây (đơn giản hóa):

// app/api/orders/recent/route.ts

import { NextRequest, NextResponse } from "next/server";
import { getRecentOrdersForUser } from "@/lib/orders";

export async function GET(req: NextRequest) {
  const userId = req.headers.get("x-giftgenius-user-id")!;
  const orders = await getRecentOrdersForUser(userId);
  return NextResponse.json({ orders });
}

Hàm getRecentOrdersForUser sống trong lớp commerce của bạn, làm việc với CSDL và biết về cấu trúc đơn hàng. Về phía widget, nó có thể gọi route này qua window.fetch (chúng ta đã làm ở các mô-đun trước) và hiển thị thẻ giao dịch.

Kết hợp “MCP tool → API của bạn → CSDL đơn hàng → widget” mang lại cho người dùng cảm giác App có “trí nhớ” về các giao dịch, dù widget chỉ đang hiển thị trạng thái từ backend.

6. Triển khai ACP‑endpoint kiểu Next.js (đơn giản)

Giờ phác thảo cách triển khai học tập cho một ACP‑endpoint chủ chốt — tạo checkout_session. Theo đặc tả, hợp đồng khá phong phú, nhưng cho khóa học có thể giữ phần cốt lõi: nhận skuId, xác thực theo feed/CSDL, tạo session và trả về ID cùng số tiền.

Giả sử có route POST /api/checkout-sessions:

// app/api/checkout-sessions/route.ts

import { NextRequest, NextResponse } from "next/server";
import { findSkuById, createCheckoutSession } from "@/lib/checkout";

export async function POST(req: NextRequest) {
  const body = await req.json();          // { skuId: string }
  const sku = await findSkuById(body.skuId);

  if (!sku) {
    return NextResponse.json(
      { error: "SKU not found" },
      { status: 400 },
    );
  }

  const session = await createCheckoutSession(sku);
  return NextResponse.json({ session });
}

Có vài điểm quan trọng.

Thứ nhất, chính tại đây lớp commerce đối chiếu Product Feed/CSDL: findSkuById phải nhìn vào cùng nguồn đã sinh ra feed. Chúng ta không tin bất cứ thứ gì “từ trên trời rơi xuống” — dù từ GPT hay widget.

Thứ hai, ta chỉ trả thứ ChatGPT/ACP‑client cần: ID session, số tiền, đơn vị tiền tệ và trạng thái (mặc định pending hoặc not_ready_for_payment, tùy thuật ngữ bạn chọn). Trong ACP thực tế có nhiều trường hơn, gồm các phương thức thanh toán và fulfillment, nhưng ví dụ học tập tập trung vào bước tạo session ban đầu.

Thứ ba, route này rất phù hợp để viết contract test: nếu mai này cấu trúc Product Feed đổi, test cho findSkuByIdcreateCheckoutSession sẽ bắt lỗi sớm, trước khi ChatGPT trả về lỗi kỳ lạ cho người dùng.

7. Liên kết giữa ACP‑session và nhà cung cấp thanh toán

Đến giờ ta chưa đụng vào nhà cung cấp thanh toán. Trong tích hợp thực tế, diễn ra đại khái như sau (đơn giản hóa).

Đầu tiên, ChatGPT (qua ACP) gọi POST /checkout_sessions của bạn. Backend của bạn tạo session nội bộ trong CSDL. Khi người dùng xác nhận thanh toán trong UI Instant Checkout, nền tảng yêu cầu PSP cấp delegated payment token (Shared Payment Token) cho merchant và số tiền cụ thể. Token này đến với bạn trong yêu cầu complete (hoặc lệnh tương đương theo Delegated Payment Spec).

Sau đó bạn tạo payment tại PSP bằng token, mà không cần truy cập dữ liệu thanh toán thực. PSP gửi webhook về kết quả; bạn cập nhật trạng thái đơn hàng và/hoặc checkout‑session.

Trong mã học tập, ta có thể mô phỏng bước này. Ví dụ, hàm completeCheckoutSession có thể như sau:

// src/lib/checkout.ts

export async function completeCheckoutSession(sessionId: string, spt: string) {
  // Thực tế sẽ gọi PSP API với delegated token (SPT)
  const paymentOk = await mockChargeWithToken(spt);

  return paymentOk
    ? { status: "succeeded" as const }
    : { status: "failed" as const };
}

Gọi PSP và dùng Shared Payment Token là phần của chuẩn Delegated Payment, còn mockChargeWithToken là lớp kiến trúc học tập của chúng ta, mô phỏng đặc thù này.

8. Luồng xuyên suốt GiftGenius: từ yêu cầu đến quà tặng đã trả tiền

Giờ ghép tất cả lại theo chuỗi bước. Đây là “câu chuyện chiến đấu” của GiftGenius, lý do chúng ta kết hợp mọi lớp. Quan trọng là không trộn lẫn hai thế giới, nên hãy xét riêng từng cái.

Sơ đồ A: không có App, chỉ Product Feed + ACP

Trong kịch bản này, bạn có Product Feed và ACP‑backend, nhưng không có ChatGPT App và widget. Đây là kiểu merchant Instant Checkout cổ điển.

Người dùng viết trong ChatGPT: “Gợi ý quà tặng số dưới $50”. GPT dùng Product Feed của bạn để tìm SKU phù hợp và hiển thị bằng UI native của nó dưới dạng thẻ mua sắm. Chưa có React code của bạn — các thẻ hoàn toàn do ChatGPT render.

Người dùng click vào nút “Buy” trên một thẻ như vậy. Cú click này được xử lý bởi chính ChatGPT. Nền tảng:

  1. Tạo line_items dựa trên Product Feed.
  2. Gọi POST /checkout_sessions của bạn theo Agentic Checkout Spec.
  3. Hiển thị cho người dùng UI Instant Checkout (phương thức thanh toán, địa chỉ, v.v.).
  4. Sau khi xác nhận, nhận Shared Payment Token từ PSP và gọi .../complete của bạn.
  5. Nhận trạng thái cuối cùng của checkout_session từ bạn và khi cần thì đợi webhook về đơn hàng.

Về phía mã của bạn, chỉ ACP‑endpoint và Product Feed hoạt động. Không có Apps SDK, window.openai hay widget. Và đây hoàn toàn là kịch bản hợp lệ, “thuần” ACP‑merchant.

Sơ đồ B: có ChatGPT App và widget GiftGenius

Giờ thêm ChatGPT App và widget GiftGenius vào. Product Feed và ACP‑backend vẫn còn nguyên: chúng tiếp tục đảm bảo tìm kiếm và thanh toán. Khác biệt ở chỗ chúng ta có UI và logic bước đi riêng trong App.

Hãy hình dung hội thoại: người dùng viết “Gợi ý quà cho mẹ dưới 50$”. GPT hiểu đây là yêu cầu commerce và đề nghị dùng GiftGenius‑App. Widget hỏi vài câu làm rõ: tuổi, sở thích, quốc gia. Sau đó GPT gọi MCP‑tool của bạn search_gifts với bộ lọc; máy chủ MCP truy vấn catalog (CSDL hoặc chỉ mục chuẩn bị sẵn), tìm vài SKU phù hợp và trả về dạng có cấu trúc.

GPT chuyển dữ liệu này cho widget, và widget hiển thị các thẻ quà tặng “đặc sản” của mình (các React component, carousel, v.v.). Đây là thiết kế và UX của bạn, không phải shopping‑UI chuẩn của ChatGPT.

Khi người dùng click nút “Mua” trong widget, diễn biến khác với sơ đồ A. Cú click này được xử lý bởi widget:

  1. Widget hiểu người dùng đã chọn SKU nào.
  2. Qua API của chính nó (ví dụ, POST /api/checkout-sessions) gọi backend của bạn để tạo checkout_session (hoặc lấy ID session đã chuẩn bị).
  3. Sau đó widget gọi phương thức runtime của Apps SDK kiểu:
    // Xem chữ ký phương thức cập nhật trong tài liệu Apps SDK
    await window.openai.requestCheckout({
      checkoutSessionId: session.id, ...
    });
    

    Lời gọi này là sáng kiến của widget. Với ChatGPT, đây là tín hiệu: “Đã đến lúc mở Instant Checkout cho checkout_session này”.

Sau đó nền tảng ChatGPT vận hành rất giống sơ đồ A, nhưng hậu trường:

  • hiển thị UI Instant Checkout cho người dùng;
  • nhận Shared Payment Token từ PSP;
  • gọi ACP‑endpoint hoàn tất session của bạn (.../complete);
  • tham gia nhận và xử lý webhook từ backend của bạn.

Tức là trong sơ đồ B, widget khởi phát checkout qua Apps SDK, còn các cuộc gọi ACP (tạo/hoàn tất checkout_session) xảy ra hoặc trước đó (khi bạn tự tạo session ở backend), hoặc ngay sau requestCheckout, nhưng luôn ở phía server.

Trong khi đó, widget có thể song song hiển thị các bước “Thanh toán”, trạng thái và bản xem trước đơn hàng, dựa trên API của bạn (/api/orders/...) và các MCP‑tool.

Nếu vẽ sơ đồ B dưới dạng biểu đồ, nó sẽ như sau:

sequenceDiagram
  participant User as Người dùng
  participant GPT as ChatGPT / GPT
  participant W as GiftGenius Widget
  participant MCP as Máy chủ MCP
  participant ACP as Commerce Backend
  participant PSP as Nhà cung cấp thanh toán

  User->>GPT: "Gợi ý quà tặng dưới $50"
  GPT->>MCP: search_gifts(...)
  MCP-->>GPT: danh sách SKU
  GPT->>W: dữ liệu để render thẻ
  User->>W: nhấp "Mua"
  W->>ACP: POST /api/checkout-sessions (skuId)
  ACP-->>W: checkout_session (id, tổng tiền, đơn vị tiền tệ)
  W->>GPT: window.openai.requestCheckout({ checkoutSessionId })
  GPT->>User: UI Instant Checkout
  User->>GPT: xác nhận thanh toán
  GPT->>PSP: yêu cầu Shared Payment Token
  PSP-->>GPT: SPT
  GPT->>ACP: complete(sessionId, SPT)
  ACP->>PSP: charge(SPT)
  PSP-->>ACP: kết quả thanh toán
  ACP->>GPT: trạng thái đơn hàng
  GPT->>User: thông báo thanh toán thành công/không thành công

Khác biệt then chốt với sơ đồ A:

  • Ở A, thẻ và nút “Buy” do chính ChatGPT render, và nó trực tiếp khởi phát gọi ACP.
  • Ở B, thẻ và nút “Mua” do widget của bạn render, và chính nó gọi window.openai.requestCheckout(...). Sau đó ChatGPT hậu trường nói chuyện với ACP‑backend và PSP của bạn.

Insight

Trong SDK của mình, ChatGPT viết rằng tính năng kiếm tiền trong ứng dụng sẽ sớm xuất hiện. Quả đúng như vậy. Các widget đã có sẵn vài phương thức chưa công bố. Và hấp dẫn nhất là requestCheckout().

Cách gọi trông như sau:

window.openai.requestCheckout({
  id: "checkout_session_123",

  payment_provider: {
    merchant_id: "stripe",
    supported_payment_methods: ["card"]
  },
   ...
}

Nó hiển thị hộp thoại để người dùng hoàn tất thanh toán. Vì thế hãy thiết kế ứng dụng như thể tính năng kiếm tiền đã bật sẵn: khi bạn hoàn thành, thực tế sẽ đúng như vậy.

9. Bản mini cho khóa học: backend gần như đơn khối

Trong các mô-đun về kiến trúc đã đặt câu hỏi: làm tất cả trong một service hay tách ngay thành máy chủ MCP, commerce‑backend và service riêng cho tích hợp thanh toán. Với mục tiêu học tập, thường “gần đơn khối” là đủ: một repo, một deploy, nhưng logic tách lớp gọn gàng.

Phương án học tập cho GiftGenius có thể như sau: ứng dụng Next.js, trong đó:

  • widget nằm ở app/widget/page.tsx;
  • các ACP‑endpoint — ở app/api/checkout-sessions và các route lân cận;
  • các công cụ MCP — ở app/api/mcp/route.ts hoặc thư mục riêng;
  • xử lý đơn hàng — ở src/lib/orders.ts, src/lib/checkout.ts và các module gần đó.

Về mặt vật lý, đây là một máy chủ (đặc biệt ở môi trường dev/staging), nhưng về mặt logic, bạn đã suy nghĩ theo 3 vai trò: UI (widget), MCP (công cụ/tài nguyên cho GPT) và ACP (commerce‑backend).

Sau này, ở mô-đun về production, bạn sẽ thấy cách “đơn khối” này được tách thành nhiều service và môi trường, phía trước là MCP Gateway. Nhưng ở cấp mô-đun 14, “đơn khối có phân lớp đúng” đã cho kiến trúc rất giống thực tế.

10. Bài tập thực hành: kiến trúc của bạn quanh ACP

Để mọi thứ trên không chỉ là lý thuyết, hãy áp vào domain của bạn ngay bây giờ. Trong phạm vi bài giảng, có thể làm hai bài tập nhỏ.

Thứ nhất, chọn kịch bản riêng: thuê bao SaaS, đặt chỗ, giao đồ ăn, khóa học online — bất kỳ case nào có sản phẩm/dịch vụ, giá và checkout hợp lý. Nhớ mô hình theo pha: discovery → decision → checkout → post‑payment.

Thứ hai, dựa vào kiến trúc GiftGenius, mô tả tự do: bạn sẽ xây Product Feed thế nào (SKU và giá ở đâu, ai cập nhật), triển khai hợp đồng ACP ở đâu (service riêng hay một phần backend hiện có), kết nối nhà cung cấp thanh toán ra sao và widget (nếu có) sẽ tương tác với tất cả thông qua MCP và Apps SDK như thế nào.

Hữu ích nếu nói rõ dự án của bạn sẽ dùng chỉ sơ đồ A (Instant Checkout không App), chỉ sơ đồ B (App + widget), hay cả hai cùng lúc. Ngay cả một bản phác thảo kiến trúc dạng text như vậy cũng giảm mạnh rủi ro bất ngờ ở giai đoạn tích hợp thực.

11. Lỗi thường gặp khi tích hợp Product Feed, ACP và widget

Lỗi số 1: hai catalog khác nhau — một cho tìm kiếm, một cho checkout.
Đôi khi đội ngũ dựng nhanh một feed “tìm kiếm” cho GPT (ví dụ, JSON nhỏ), rồi sau đó lại làm CSDL commerce cho đơn hàng. Nếu chúng không liên kết bằng ID chung và logic cập nhật chung, GPT có thể đề xuất sản phẩm đã không còn bán được hoặc với giá cũ. Cách đúng — một nguồn chân lý, từ đó sinh ra cả Product Feed lẫn bảng nội bộ cho ACP‑endpoint.

Lỗi số 2: tin tưởng dữ liệu đến từ GPT hoặc widget.
Khi trong checkout_sessionskuId và giá, rất dễ muốn tin ngay: “GPT sẽ không bịa đâu”. Nhưng mô hình có thể “sáng tạo” hoặc nhầm SKU, còn người dùng có thể cố hack yêu cầu. Nếu không đối chiếu dữ liệu vào với Product Feed/CSDL, bạn có nguy cơ bán sai mặt hàng hoặc sai giá. Mọi ACP‑endpoint phải bắt đầu bằng xác thực với kho lưu trữ catalog sơ cấp.

Lỗi số 3: trộn lẫn vai trò của widget và commerce‑backend.
Đôi khi dev theo thói quen gọi ngay SDK thanh toán từ frontend, tạo session ở Stripe và sống như một website thường. Trong ngữ cảnh ChatGPT Apps, điều này phá vỡ mô hình bảo mật và trái với ACP: luồng thanh toán phải đi qua ChatGPT và commerce‑backend của bạn, còn widget chỉ hiển thị trạng thái và gửi sự kiện (như requestCheckout). Nếu widget biết quá nhiều về vùng thanh toán, bạn sẽ có cả độ phức tạp lẫn rủi ro tăng cao.

Lỗi số 4: đơn giản hóa quá mức hợp đồng ACP.
Trong ví dụ học tập, chúng ta cố ý chỉ giữ skuId, tổng tiền và trạng thái để không sa vào chi tiết. Vấn đề xuất hiện khi “hợp đồng demo” lặng lẽ trôi vào production. Bạn bỗng thấy thiếu trường địa chỉ, thuế, phương thức giao hàng, mã khuyến mãi, rồi bắt đầu “vá” một cách hỗn loạn. Tốt hơn là thiết kế mô hình nội bộ có dư địa cho kịch bản thực ngay từ đầu, dù một số trường ban đầu chưa dùng.

Lỗi số 5: thiếu liên kết giữa đơn hàng và người dùng.
Trong demo, dễ dừng ở orderIdskuId, không nghĩ đến việc người dùng sẽ quay lại sau một tuần và hỏi: “Hiển thị các mua sắm của tôi”. Nếu ngay từ đầu không đặt userId (hoặc định danh bền vững khác) vào đơn hàng và checkout‑session, sau này bạn sẽ phải di trú dữ liệu và bắc cầu phức tạp. Kiến trúc commerce quanh ChatGPT hầu như luôn giả định GPT có thể liên hệ cuộc trò chuyện hiện tại với lịch sử đơn hàng của người dùng — hãy tính trước điều đó.

Lỗi số 6: đánh giá thấp tầm quan trọng của webhook và tính idempotent.
Trong bài giảng, chúng ta mới chỉ nói về webhooks, đào sâu sẽ ở mô-đun sau. Dễ nghĩ rằng: “webhook đến một lần, cập nhật đơn là xong”. Thực tế, hệ thống thanh toán thích retry sự kiện, còn mạng thì đánh rơi phản hồi. Nếu không thiết kế đơn hàng và checkout‑session theo hướng idempotent (theo checkoutSessionId hoặc paymentId), bạn có thể gặp trừ tiền hai lần, trùng đơn và sai lệch khó lường giữa PSP và CSDL của bạn.

Lỗi số 7: bỏ qua hạn chế và chính sách trong Product Feed.
Chạy theo feed demo nhanh rất dễ quên giới hạn độ tuổi, khu vực, danh mục cấm và các “tiểu tiết” khác. Sau đó GPT có thể đề xuất cho người dùng sản phẩm không được bán ở vùng của họ hoặc không phù hợp độ tuổi. Các trường liên quan đến chính sách và hạn chế cần được thiết kế và điền ngay từ đầu, dù hiện tại bạn chỉ bán quà tặng số vô hại.

1
Khảo sát/đố vui
, cấp độ , bài học
Không có sẵn
Thanh toán: ACP và Instant Checkout
Thương mại: Product Feed, ACP và Instant Checkout
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION