Tích Hợp Thanh Toán
Tích hợp thanh toán là tác vụ mà mọi team đều biết sắp phải làm và không ai thích xây dựng. SDK của từng provider khác nhau, webhook signature dễ bị làm sai, và một edge case bị bỏ qua có nghĩa là tiền không được thu hoặc bị tính gấp đôi. Sun Agent Kit tạo scaffold tích hợp thanh toán hoàn chỉnh, sẵn sàng cho production — bao gồm webhook handler theo từng provider, idempotency key, và reconciliation logging — để team bạn ship một checkout hoạt động thực sự, không phải prototype.
Tổng Quan
Mục tiêu: Tích hợp payment provider end-to-end: checkout session, webhook handling, subscription management, và refund
Thời gian: 25–50 phút (so với 5–10 giờ đọc tài liệu, viết boilerplate, và debug webhook)
Agent sử dụng: planner, implementer, tester, reviewer
Lệnh: /sk:cook, /sk:scout, /sk:security-scan, /sk:test
Yêu Cầu Trước Khi Bắt Đầu
- Sun Agent Kit đã được cài đặt và xác thực (hướng dẫn cài đặt)
- Một ứng dụng backend đang chạy (Node.js/Express, Python/FastAPI, Laravel, hoặc Spring Boot)
- Tài khoản payment provider với API key sẵn có (lưu trong
.env, không bao giờ hardcode) - Webhook endpoint có thể truy cập từ internet (dùng
ngrokhoặc tương tự để dev local) - Database có bảng
paymentshoặcorders(agent sẽ tạo migration nếu chưa có)
Quy Trình Từng Bước
Bước 1: Scout codebase hiện tại để tìm code liên quan đến thanh toán
Trước khi sinh code bất kỳ thứ gì, agent lập bản đồ những gì đã có — logic cart hiện tại, order model, và bất kỳ tích hợp nào đã làm một phần.
/sk:scout "payment, checkout, order, cart, billing, subscription, invoice"
Điều gì xảy ra: Agent thực hiện:
- Quét repository để tìm pattern liên quan đến thanh toán trong controller, model, và cấu hình
- Lập bản đồ bề mặt tích hợp — framework, ORM, phương thức auth
- Xác định những gì đã có (order model, cart logic) và những gì còn thiếu (webhook handler, subscription management)
- Tạo blueprint tích hợp lưu vào
plans/reports/
Bước 2: Chọn payment provider và sinh tích hợp
Nói với agent provider nào (hoặc các provider nào) bạn cần và những luồng thanh toán nào được yêu cầu.
/sk:cook "Stripe payment integration with one-time checkout and subscription support, using Prisma and Express"
Điều gì xảy ra: Agent thực hiện:
- Cài đặt provider SDK và tạo checkout session handler với idempotency key pattern
- Sinh các route subscription management (subscribe, cancel, check status)
- Xây dựng webhook handler với signature verification cho các loại event chính
- Tạo database migration cho subscription và payment audit log
- Viết unit test bao gồm happy path và failure scenario
Bước 3: Thêm payment provider thứ hai (SePay cho thị trường Việt Nam)
Với các dự án phục vụ cả thị trường quốc tế và Việt Nam, thêm SePay như một phương thức thanh toán thay thế bên cạnh Stripe.
/sk:cook "Add SePay payment gateway alongside existing Stripe integration. SePay handles VND bank transfers for Vietnamese customers."
Điều gì xảy ra: Agent thực hiện:
- Sinh SePay checkout handler với xử lý tiền tệ VND và tạo QR code
- Xây dựng SePay webhook handler với xác minh HMAC-SHA256 signature
- Triển khai logic routing dựa trên tiền tệ (VND → SePay, các loại khác → Stripe)
- Viết test cho luồng thanh toán SePay
Bước 4: Cấu hình webhook và test local
Webhook là phần hay bị hỏng im lặng trên production. Agent thiết lập cấu hình xác minh và script test.
/sk:cook "Test payment webhooks locally with stripe-cli and verify all event types are handled"
Điều gì xảy ra: Agent thực hiện:
- Xác minh cấu hình webhook local và secret trong
.env - Tạo script test webhook bao gồm các loại event chính
- Xác nhận mỗi event handler tạo ra các bản ghi database mong đợi
Bước 5: Scan bảo mật code thanh toán
Code thanh toán là mục tiêu có giá trị cao. Chạy scan tập trung trước khi commit.
/sk:security-scan src/payments/ src/webhooks/
Điều gì xảy ra: Agent thực hiện:
- Kiểm tra webhook signature được xác minh trước khi xử lý
- Xác nhận idempotency key được dùng trên tất cả mutation endpoint
- Xác minh không có raw card data nào được lưu hoặc log
- Xác nhận amount validation phía server (không tin tưởng giá từ client)
- Đánh dấu các biện pháp bảo mật còn thiếu (ví dụ: rate limiting)
Ví Dụ Hoàn Chỉnh: E-Commerce Việt Nam Cần Tích Hợp Song Song SePay + Stripe
Tình huống
Một khách hàng thời trang e-commerce Việt Nam đang mở rộng ra thị trường quốc tế. Backend Laravel hiện tại của họ có luồng thanh toán khi nhận hàng cơ bản. Yêu cầu mới: khách hàng Việt Nam thanh toán qua SePay chuyển khoản ngân hàng (QR code), khách hàng quốc tế thanh toán qua thẻ Stripe. Cả hai luồng phải cập nhật cùng bảng orders, và chủ doanh nghiệp cần một báo cáo đối soát thống nhất. Deadline là cuối sprint — năm ngày làm việc.
Chuỗi lệnh sử dụng
# Ngày 1 buổi sáng — hiểu những gì đang có
/sk:scout "payment, order, checkout, cart"
# Ngày 1 buổi chiều — scaffold cả hai provider cùng lúc
/sk:cook "Dual payment integration for Laravel: Stripe for international customers (USD/EUR), SePay for Vietnamese customers (VND). Shared orders table, unified reconciliation log."
# Ngày 2 buổi sáng — thêm subscription support (khách hàng cũng bán monthly box)
/sk:cook "Add monthly subscription support to Stripe integration — Stripe Billing, plan management, cancellation flow"
# Ngày 2 buổi chiều — test webhook handling kỹ lưỡng
/sk:test "comprehensive webhook tests for both Stripe and SePay handlers — test idempotency, signature failure, duplicate event rejection"
# Ngày 3 — security review trước demo
/sk:security-scan --full
# Ngày 4 — tạo tài liệu tích hợp cho khách hàng
/sk:docs "Payment integration guide for client handoff — cover both Stripe and SePay, webhook setup, .env variables, reconciliation query"
Kết quả
Đến ngày thứ tư, khách hàng có một checkout hai provider hoạt động, một pipeline webhook đã được test xử lý tất cả edge case, và một câu query đối soát kết hợp cả hai nguồn thanh toán thành một dashboard view duy nhất. Tài liệu bàn giao cung cấp cho team nội bộ của họ mọi thứ cần thiết để quản lý tích hợp về sau.
So Sánh Thời Gian
| Tác vụ | Thủ công | Với Sun Agent Kit |
|---|---|---|
| Đọc tài liệu Stripe SDK + boilerplate | 90 phút | vài phút |
| Viết checkout session + xử lý lỗi | 60 phút | vài phút |
| Xây dựng webhook handler với sig verification | 45 phút | vài phút |
| Nghiên cứu SePay API + triển khai | 90 phút | vài phút |
| Viết tests cho payment flow | 60 phút | vài phút |
| Security review code thanh toán | 30 phút | vài phút |
| Tổng cộng | ~6 giờ | dưới 30 phút |
Thực Hành Tốt Nhất
1. Luôn validate amount phía server, không bao giờ tin tưởng client ✅
Agent áp dụng pattern này theo mặc định — checkout session luôn lấy giá từ database bằng price_id hoặc product_id, không bao giờ từ trường amount do client cung cấp. Điều này ngăn chặn tấn công price manipulation.
2. Dùng payment_events audit log cho tất cả webhook processing ✅
Webhook handler được scaffold ghi mỗi event nhận được vào bảng payment_events trước khi xử lý nó. Điều này cung cấp idempotency (bỏ qua event ID đã xử lý), một trail đối soát, và một bề mặt debug khi thanh toán “bí ẩn” không settle.
3. Đừng bao giờ log toàn bộ payload thanh toán trong production ❌
Payload của Stripe và SePay có thể chứa số thẻ một phần và thông tin thanh toán nhạy cảm. Code được sinh chỉ log event type và event ID. Đừng thêm console.log(event) hoặc Log::debug($event) để debug vấn đề webhook trong production — dùng dashboard của provider thay thế.
4. Đừng bỏ qua bước xác minh webhook signature, kể cả trên staging ❌
Thật hấp dẫn khi comment out signature verification khi debug local. Điều này tạo ra thói quen cuối cùng lọt vào production deploy. Luôn giữ signature verification hoạt động và dùng CLI tool của provider (ví dụ: stripe listen) để test local.
Xử Lý Sự Cố
Vấn đề: Webhook event được nhận nhưng order không được tạo — không có lỗi trong log
Giải pháp: Nguyên nhân phổ biến nhất là thiếu Content-Type: application/json trên raw request body dùng để xác minh signature. Express (và nhiều framework) parse body trước khi webhook handler thấy nó, phá hủy raw buffer cần thiết cho xác minh HMAC. Handler được sinh dùng express.raw({ type: 'application/json' }) làm middleware — đảm bảo không có global JSON parser nào chạy trước nó trên webhook route.
Vấn đề: Thanh toán QR code SePay không bao giờ kích hoạt webhook
Giải pháp: SePay yêu cầu webhook callback URL phải được đăng ký trong merchant dashboard và phải là HTTPS. Trong môi trường dev local, xác nhận URL ngrok tunnel của bạn đã được đăng ký. Trong staging, xác nhận server có thể truy cập từ IP range của SePay và SEPAY_WEBHOOK_SECRET trong .env khớp với giá trị trong dashboard.
Vấn đề: Webhook hủy subscription Stripe kích hoạt nhưng quyền truy cập người dùng không bị thu hồi
Giải pháp: Kiểm tra handler của bạn có lắng nghe customer.subscription.deleted (không phải customer.subscription.updated). Hủy vào cuối kỳ kích hoạt customer.subscription.updated với cancel_at_period_end: true — quyền truy cập nên vẫn hoạt động cho đến current_period_end. Handler được sinh xử lý cả hai event; xác minh bạn chưa xóa nhánh customer.subscription.updated.
Vấn đề: Order bị tạo trùng lặp khi retry
Giải pháp: Chạy /sk:cook "Add idempotency key handling to Stripe checkout session creation" để scaffold idempotency pattern. Stripe API chấp nhận header Idempotency-Key — sinh nó dưới dạng sha256(userId + cartId + timestamp_minute) để các retry trong cùng một phút tái sử dụng session hiện có.
Bước Tiếp Theo
- Kiểm Tra Bảo Mật — Chạy security audit thanh toán mục tiêu trước khi go live
- Tối Ưu Hiệu Suất — Đảm bảo payment endpoint của bạn xử lý được traffic spike mà không bị timeout
- Tạo Tài Liệu Tự Động — Tạo tài liệu bàn giao cho khách hàng bao gồm cấu hình thanh toán
Điểm mấu chốt: Tích hợp thanh toán quá dễ xảy ra lỗi để code tay dưới áp lực deadline — agent scaffold tích hợp hoàn chỉnh, được hardened về bảo mật để team bạn tập trung vào business logic, không phải boilerplate.