0
0
Lập trình
Flame Kris
Flame Krisbacodekiller

Cách Kiểm Tra Chu Kỳ Thanh Toán Stripe Trong 5 Phút

Đăng vào 3 tuần trước

• 6 phút đọc

Cách Kiểm Tra Chu Kỳ Thanh Toán Stripe Trong 5 Phút

Nếu bạn đã từng triển khai một tính năng thanh toán và hy vọng nó "chỉ hoạt động", thì bài viết này dành cho bạn.

🧪 Câu Hỏi Tồn Tại Của Lập Trình Viên: "Làm Thế Nào Để Kiểm Tra Thanh Toán?"

Bạn vừa triển khai gói Pro với giá 250 USD/tháng và giai đoạn dùng thử 7 ngày. QA vào với câu hỏi đáng sợ:

"Vậy... làm thế nào để chúng ta thực sự kiểm tra toàn bộ vòng đời thanh toán?"

Và bạn đứng hình.

Hãy phân tích các lựa chọn của bạn:

  • Chờ thực tế (7+ ngày, rồi thêm 30 ngày cho chu kỳ tiếp theo 😴)
  • Chỉnh sửa timestamp trong cơ sở dữ liệu (hỏng, dễ bị lỗi webhook)
  • Giả lập Stripe (nhanh nhưng thiếu hành vi thực tế)
  • Triển khai và cầu nguyện (đừng giả vờ là bạn chưa bao giờ làm điều này 😅)

Không có lựa chọn nào là tốt cả. Chu kỳ thanh toán thực tế của Stripe cần thời gian thực, điều này không phù hợp cho CI/CD hoặc lặp lại nhanh.

Vì vậy, chúng tôi đã tìm ra một cách tốt hơn.

🧠 Tóm Tắt Ngắn Gọn – Công Nghệ Chúng Tôi Đã Sử Dụng

Chúng tôi đã xây dựng một bộ kiểm tra thanh toán nhanh và lặp lại bằng cách sử dụng:

  • ✅ Stripe Test Clocks để mô phỏng thời gian
  • ✅ Playwright cho toàn bộ trải nghiệm E2E (bao gồm UI + webhook)
  • ✅ API backend để quản lý đồng hồ thử nghiệm một cách an toàn
  • ✅ Trợ giúp kiểm tra TypeScript để điều khiển mọi thứ

Toàn bộ vòng đời thanh toán (thử nghiệm → thanh toán → gia hạn) được xác minh trong dưới 5 phút.

Cài Đặt Hệ Thống: Stripe Test Clocks + Playwright

Dưới đây là cách hệ thống được cấu trúc:

1. API Backend (Node.js / TypeScript)

  • Tạo và nâng cấp Stripe Test Clocks một cách an toàn
  • Hạn chế các thao tác chỉ cho môi trường test / dev
  • Tổ chức việc tạo đăng ký + phối hợp webhook

2. Trợ Giúp Frontend

  • Tiện ích TypeScript cho các bài kiểm tra
  • Bọc các cuộc gọi API để tạo/nâng cấp đồng hồ
  • Xác thực trạng thái đăng ký + hóa đơn

3. Kiểm Tra E2E Bằng Playwright

  • Mô phỏng việc nâng cấp thực tế của người dùng qua UI
  • Kích hoạt quy trình thanh toán Stripe
  • Nâng cao thời gian + xác minh sự kiện thanh toán

🧩 Tại Sao Test Clocks Quan Trọng

Stripe's Test Clocks cho phép bạn:

  • Tạo một phiên bản "sandbox" của thời gian
  • Gắn các tài nguyên (khách hàng, đăng ký) vào đồng hồ đó
  • Di chuyển thời gian tới (ví dụ: +7 ngày, +30 ngày)
  • Quan sát cách hành vi thanh toán qua các ranh giới thời gian

Rất phù hợp cho CI, tái hiện lỗi hoặc xác thực các trường hợp biên phức tạp trong thanh toán.

🛠️ Điểm Nổi Bật Trong Mã: Cách Thức Hoạt Động

Tạo Một Test Clock

typescript Copy
export const createTestClock = async (frozenTime: Date) => {
  ensureTestEnvironment(); // An toàn là trên hết
  return await stripe.testHelpers.testClocks.create({
    frozen_time: Math.floor(frozenTime.getTime() / 1000),
    name: `billing-test-${Date.now()}`,
  });
};

✅ Chỉ được phép trong môi trường test/dev (chúng tôi thực thi điều này ở mọi lớp)

Nâng Cao Thời Gian & Chờ Webhooks

Việc nâng cao thời gian không đủ — bạn cũng cần chờ Stripe xử lý webhook:

typescript Copy
export const advanceTestClockAndWait = async (
  testClockId: string,
  targetTime: string
) => {
  await stripe.testHelpers.testClocks.advance(testClockId, {
    frozen_time: Math.floor(new Date(targetTime).getTime() / 1000),
  });

  // Poll cho đến khi webhook được xử lý
  await waitForWebhookProcessing(testClockId);
};

Logic Xác Minh Thanh Toán

Bạn sẽ muốn xác minh:

  • Trạng thái đăng ký (đang thử nghiệm, đang hoạt động, v.v.)
  • Hóa đơn được tạo + đã thanh toán
  • Số tiền chính xác (hóa đơn dùng thử $0 so với $250 đang hoạt động)
typescript Copy
export const verifyBillingLifecycle = async (
  page: Page,
  customerId: string,
  subscriptionId: string
) => {
  const response = await page.request.post('/api/v1/billing/test/verify', {
    data: { customerId, subscriptionId },
  });

  return response.json();
};

🧪 Ví Dụ Thực Tế: Thử Nghiệm → Thanh Toán → Gia Hạn

Hãy cùng đi qua một bài kiểm tra vòng đời thanh toán đầy đủ trong Playwright.

1. Tạo một thời gian đông lạnh

typescript Copy
const frozenTime = new Date();
frozenTime.setHours(0, 0, 0, 0);

2. Thiết lập môi trường

typescript Copy
const testEnv = await createTestClockEnvironment(page, accountId, 'pro', 'monthly', frozenTime.toISOString());

3. Người dùng nâng cấp lên Pro qua UI

typescript Copy
await subscriptionPage.upgradeToProPlan('monthly');
await completeStripeCheckout(page, STRIPE_TEST_CARDS.VISA_SUCCESS);

4. Xác minh trạng thái dùng thử

typescript Copy
const result = await verifyBillingLifecycle(
  page,
  testEnv.customer.id,
  testEnv.subscription.id,
);
expect(result.subscription.status).toBe('trialing');

5. Nâng cao 8 ngày (sau giai đoạn dùng thử)

typescript Copy
await advanceTestClockAndWaitForWebhooks(
  page,
  testEnv.testClock.id,
  addDays(frozenTime, 8).toISOString()
);

6. Xác minh khoản phí đầu tiên ($250)

typescript Copy
const invoices = await verifyBillingLifecycle(...);
expect(invoices.total).toBeGreaterThan(0);

7. Nâng cao thêm 30 ngày → Thanh toán lần hai

typescript Copy
await advanceTestClockAndWaitForWebhooks(
  page,
  testEnv.testClock.id,
  addDays(frozenTime, 40).toISOString()
);

8. Xác minh khoản phí thứ hai ($250 nữa)

typescript Copy
const updated = await verifyBillingLifecycle(...);
expect(updated.invoices.details.length).toBe(2);

Tổng thời gian kiểm tra: < 5 phút
Thời gian thực tế tương đương: 40+ ngày

⚠️ Bài Học Rút Ra (Từ Kinh Nghiệm)

✅ Cách Ly Môi Trường Là Quan Trọng

Chúng tôi đã thêm kiểm tra ensureTestEnvironment() vào mọi hàm. Bạn không muốn các đồng hồ thử nghiệm chạy trong môi trường sản xuất.

✅ Cần Xử Lý Webhook Bằng Cách Polling

Thời gian cố định không đủ. Chúng tôi đã xây dựng một hệ thống polling để kiểm tra tính sẵn sàng của webhook trước khi tiếp tục.

✅ Dọn Dẹp Hoặc Bị Lộn Xộn

Các đồng hồ thử nghiệm + đăng ký tích lũy rất nhanh. Chúng tôi tự động dọn dẹp khi tháo gỡ và cung cấp các điểm cuối dọn dẹp thủ công.

🚀 Tại Sao Điều Này Quan Trọng

Trước:

  • Kiểm tra thủ công trong môi trường phát triển
  • Không có cách nào để kiểm tra toàn bộ chu kỳ trước khi sản xuất

Sau:

  • Thời gian kiểm tra nhanh hơn 99.99%
  • Toàn bộ trải nghiệm E2E (dùng thử, phí, gia hạn)
  • Các bài kiểm tra giống nhau chạy trong CI và địa phương
  • Không có bất ngờ trong sản xuất

🧼 Dọn Dẹp Để Thành Công

Chúng tôi tự động hủy bỏ các đăng ký thử nghiệm và xóa các đồng hồ:

typescript Copy
export const cleanupTestClockEnvironment = async (testClockId) => {
  const subs = await getTestClockSubscriptions(testClockId);
  for (const s of subs) await stripe.subscriptions.cancel(s.id);
  await stripe.testHelpers.testClocks.del(testClockId);
};

Kết nối nó vào quá trình tháo gỡ kiểm tra của bạn:

typescript Copy
test.afterAll(async () => {
  await cleanupTestClockEnvironment(testEnvironment.testClock.id);
});

Suy Nghĩ Cuối Cùng: Kiểm Tra Thanh Toán Như Một Lập Trình Viên

Đây không phải là về việc làm đẹp các bài kiểm tra. Nó là về sự tự tin của lập trình viên.

Với Stripe Test Clocks + tự động hóa E2E, chúng tôi đã ngừng triển khai các tính năng thanh toán và cầu nguyện. Bây giờ chúng tôi biết toàn bộ vòng đời hoạt động trước khi bất kỳ điều gì đến sản xuất.

  • An toàn cho CI
  • Hoàn toàn xác định
  • Xác thực chuyển động tiền thực tế

Nếu bạn đang xây dựng một sản phẩm đăng ký và không kiểm tra như thế này... bạn chắc chắn nên làm như vậy.

Chiến Lược Kiểm Tra Thanh Toán Của Bạn Là Gì?

Bạn có đang sử dụng test clocks? Giả lập mọi thứ? Vẫn đang chạy các bài kiểm tra thủ công trong giai đoạn triển khai?

Hãy chia sẻ ý kiến, để lại một bình luận về cách bạn đang xử lý điều này hôm nay.

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào