Chuyển đến nội dung chính

Nâng cấp hoặc hạ cấp đăng ký là gì?

Thay đổi kế hoạch cho phép bạn di chuyển một khách hàng giữa các cấp độ hoặc số lượng đăng ký. Sử dụng nó để:
  • Căn chỉnh giá cả với mức sử dụng hoặc tính năng
  • Chuyển từ hàng tháng sang hàng năm (hoặc ngược lại)
  • Điều chỉnh số lượng cho các sản phẩm dựa trên ghế
Thay đổi kế hoạch có thể kích hoạt một khoản phí ngay lập tức tùy thuộc vào chế độ proration bạn chọn.

Khi nào sử dụng thay đổi kế hoạch

  • Nâng cấp khi khách hàng cần nhiều tính năng, mức sử dụng hoặc ghế hơn
  • Hạ cấp khi mức sử dụng giảm
  • Di chuyển người dùng sang sản phẩm hoặc giá mới mà không hủy đăng ký của họ

Điều kiện tiên quyết

Trước khi thực hiện thay đổi kế hoạch đăng ký, hãy đảm bảo bạn có:
  • Một tài khoản thương nhân Dodo Payments với các sản phẩm đăng ký đang hoạt động
  • Thông tin xác thực API (khóa API và khóa bí mật webhook) từ bảng điều khiển
  • Một đăng ký đang hoạt động hiện có để sửa đổi
  • Điểm cuối webhook được cấu hình để xử lý các sự kiện đăng ký
Để biết hướng dẫn thiết lập chi tiết, hãy xem Hướng dẫn Tích hợp.

Hướng dẫn Triển khai Từng Bước

Theo dõi hướng dẫn toàn diện này để thực hiện các thay đổi kế hoạch đăng ký trong ứng dụng của bạn:
1

Hiểu yêu cầu thay đổi kế hoạch

Trước khi thực hiện, xác định:
  • Các sản phẩm đăng ký nào có thể thay đổi sang các sản phẩm nào khác
  • Chế độ proration nào phù hợp với mô hình kinh doanh của bạn
  • Cách xử lý các thay đổi kế hoạch không thành công một cách nhẹ nhàng
  • Các sự kiện webhook nào cần theo dõi để quản lý trạng thái
Thử nghiệm các thay đổi kế hoạch một cách kỹ lưỡng trong chế độ thử nghiệm trước khi triển khai trong môi trường sản xuất.
2

Chọn Chiến lược Proration của Bạn

Chọn cách tính phí phù hợp với nhu cầu kinh doanh của bạn:
Tốt nhất cho: Các ứng dụng SaaS muốn tính phí công bằng cho thời gian không sử dụng
  • Tính toán số tiền proration chính xác dựa trên thời gian chu kỳ còn lại
  • Tính phí một khoản tiền proration dựa trên thời gian không sử dụng còn lại trong chu kỳ
  • Cung cấp hóa đơn minh bạch cho khách hàng
3

Thực hiện API Thay đổi Kế hoạch

Sử dụng API Thay đổi Kế hoạch để sửa đổi chi tiết đăng ký:
subscription_id
string
required
ID của đăng ký đang hoạt động để sửa đổi.
product_id
string
required
ID sản phẩm mới để thay đổi đăng ký sang.
quantity
integer
default:"1"
Số lượng đơn vị cho kế hoạch mới (đối với các sản phẩm dựa trên ghế).
proration_billing_mode
string
required
Cách xử lý thanh toán ngay lập tức: prorated_immediately, full_immediately, hoặc difference_immediately.
addons
array
Các addon tùy chọn cho kế hoạch mới. Để trống sẽ xóa bất kỳ addon hiện có nào.
4

Xử lý Sự kiện Webhook

Thiết lập xử lý webhook để theo dõi kết quả thay đổi kế hoạch:
  • subscription.active: Thay đổi kế hoạch thành công, đăng ký đã được cập nhật
  • subscription.plan_changed: Kế hoạch đăng ký đã thay đổi (nâng cấp/hạ cấp/cập nhật addon)
  • subscription.on_hold: Thay đổi phí kế hoạch không thành công, đăng ký đã bị tạm dừng
  • payment.succeeded: Tính phí ngay lập tức cho thay đổi kế hoạch đã thành công
  • payment.failed: Tính phí ngay lập tức không thành công
Luôn xác minh chữ ký webhook và thực hiện xử lý sự kiện idempotent.
5

Cập nhật Trạng thái Ứng dụng của Bạn

Dựa trên các sự kiện webhook, cập nhật ứng dụng của bạn:
  • Cấp phát/rút lại tính năng dựa trên kế hoạch mới
  • Cập nhật bảng điều khiển của khách hàng với chi tiết kế hoạch mới
  • Gửi email xác nhận về các thay đổi kế hoạch
  • Ghi lại các thay đổi thanh toán cho mục đích kiểm toán
6

Kiểm tra và Giám sát

Thử nghiệm kỹ lưỡng việc triển khai của bạn:
  • Kiểm tra tất cả các chế độ proration với các tình huống khác nhau
  • Xác minh rằng việc xử lý webhook hoạt động chính xác
  • Giám sát tỷ lệ thành công của thay đổi kế hoạch
  • Thiết lập cảnh báo cho các thay đổi kế hoạch không thành công
Việc triển khai thay đổi kế hoạch đăng ký của bạn hiện đã sẵn sàng cho việc sử dụng trong sản xuất.

Xem trước Thay đổi Kế hoạch

Trước khi cam kết thay đổi kế hoạch, hãy sử dụng API Xem trước để cho khách hàng thấy chính xác số tiền họ sẽ bị tính phí:
const preview = await client.subscriptions.previewChangePlan('sub_123', {
  product_id: 'prod_pro',
  quantity: 1,
  proration_billing_mode: 'prorated_immediately'
});

// Show customer the charge before confirming
console.log('Immediate charge:', preview.immediate_charge.summary);
console.log('New plan details:', preview.new_plan);
Sử dụng API xem trước để xây dựng các hộp thoại xác nhận cho khách hàng cho thấy chính xác số tiền họ sẽ bị tính phí trước khi họ xác nhận thay đổi kế hoạch.

API Thay đổi Kế hoạch

Sử dụng API Thay đổi Kế hoạch để sửa đổi sản phẩm, số lượng và hành vi proration cho một đăng ký đang hoạt động.

Ví dụ khởi động nhanh

import DodoPayments from 'dodopayments';

const client = new DodoPayments({
  bearerToken: process.env.DODO_PAYMENTS_API_KEY,
  environment: 'test_mode', // defaults to 'live_mode'
});

async function changePlan() {
  const result = await client.subscriptions.changePlan('sub_123', {
    product_id: 'prod_new',
    quantity: 3,
    proration_billing_mode: 'prorated_immediately',
  });
  console.log(result.status, result.invoice_id, result.payment_id);
}

changePlan();
Success
{
  "status": "processing",
  "subscription_id": "sub_123",
  "invoice_id": "inv_789",
  "payment_id": "pay_456",
  "proration_billing_mode": "prorated_immediately"
}
Các trường như invoice_idpayment_id chỉ được trả về khi một khoản phí ngay lập tức và/hoặc hóa đơn được tạo trong quá trình thay đổi kế hoạch. Luôn dựa vào các sự kiện webhook (ví dụ: payment.succeeded, subscription.plan_changed) để xác nhận kết quả.
Nếu khoản phí ngay lập tức không thành công, đăng ký có thể chuyển sang subscription.on_hold cho đến khi thanh toán thành công.

Quản lý Addons

Khi thay đổi kế hoạch đăng ký, bạn cũng có thể sửa đổi các addon:
// Add addons to the new plan
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_new',
  quantity: 1,
  proration_billing_mode: 'difference_immediately',
  addons: [
    { addon_id: 'addon_123', quantity: 2 }
  ]
});

// Remove all existing addons
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_new',
  quantity: 1,
  proration_billing_mode: 'difference_immediately',
  addons: [] // Empty array removes all existing addons
});
Các addon được bao gồm trong tính toán proration và sẽ bị tính phí theo chế độ proration đã chọn.

Chế độ Proration

Chọn cách tính phí cho khách hàng khi thay đổi kế hoạch:

prorated_immediately

  • Tính phí cho sự khác biệt một phần trong chu kỳ hiện tại
  • Nếu trong thời gian dùng thử, tính phí ngay lập tức và chuyển sang kế hoạch mới ngay bây giờ
  • Hạ cấp: có thể tạo tín dụng proration áp dụng cho các lần gia hạn trong tương lai

full_immediately

  • Tính phí toàn bộ số tiền của kế hoạch mới ngay lập tức
  • Bỏ qua thời gian còn lại từ kế hoạch cũ
Các tín dụng được tạo bởi việc hạ cấp sử dụng difference_immediately là có phạm vi đăng ký và khác với Tín dụng Khách hàng. Chúng tự động áp dụng cho các lần gia hạn trong tương lai của cùng một đăng ký và không thể chuyển nhượng giữa các đăng ký.

difference_immediately

  • Nâng cấp: tính phí ngay lập tức sự khác biệt giữa các kế hoạch cũ và mới
  • Hạ cấp: thêm giá trị còn lại như tín dụng nội bộ cho đăng ký và tự động áp dụng khi gia hạn

Các tình huống ví dụ

await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_pro',
  quantity: 1,
  proration_billing_mode: 'difference_immediately'
})
// Immediate charge: $50
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_starter',
  quantity: 1,
  proration_billing_mode: 'difference_immediately'
})
// Credit added: $30 (auto-applied to future renewals for this subscription)
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_new',
  quantity: 1,
  proration_billing_mode: 'prorated_immediately'
})
// Immediate prorated charge based on remaining days in cycle
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_new',
  quantity: 1,
  proration_billing_mode: 'full_immediately'
})
// Immediate full charge for new plan; no credits calculated
Chọn prorated_immediately cho kế toán công bằng về thời gian; chọn full_immediately để khởi động lại thanh toán; sử dụng difference_immediately cho các nâng cấp đơn giản và tín dụng tự động khi hạ cấp.

Xử lý webhooks

Theo dõi trạng thái đăng ký thông qua webhooks để xác nhận các thay đổi kế hoạch và thanh toán.

Các loại sự kiện cần xử lý

  • subscription.active: đăng ký đã được kích hoạt
  • subscription.plan_changed: kế hoạch đăng ký đã thay đổi (nâng cấp/hạ cấp/các thay đổi addon)
  • subscription.on_hold: phí không thành công, đăng ký đã bị tạm dừng
  • subscription.renewed: gia hạn đã thành công
  • payment.succeeded: thanh toán cho thay đổi kế hoạch hoặc gia hạn đã thành công
  • payment.failed: thanh toán không thành công
Chúng tôi khuyên bạn nên điều khiển logic kinh doanh từ các sự kiện đăng ký và sử dụng các sự kiện thanh toán để xác nhận và đối chiếu.

Xác minh chữ ký và xử lý ý định

import { NextRequest, NextResponse } from 'next/server';

export async function POST(req) {
  const webhookId = req.headers.get('webhook-id');
  const webhookSignature = req.headers.get('webhook-signature');
  const webhookTimestamp = req.headers.get('webhook-timestamp');
  const secret = process.env.DODO_WEBHOOK_SECRET;

  const payload = await req.text();
  // verifySignature is a placeholder – in production, use a Standard Webhooks library
  const { valid, event } = await verifySignature(
    payload,
    { id: webhookId, signature: webhookSignature, timestamp: webhookTimestamp },
    secret
  );
  if (!valid) return NextResponse.json({ error: 'Invalid signature' }, { status: 400 });

  switch (event.type) {
    case 'subscription.active':
      // mark subscription active in your DB
      break;
    case 'subscription.plan_changed':
      // refresh entitlements and reflect the new plan in your UI
      break;
    case 'subscription.on_hold':
      // notify user to update payment method
      break;
    case 'subscription.renewed':
      // extend access window
      break;
    case 'payment.succeeded':
      // reconcile payment for plan change
      break;
    case 'payment.failed':
      // log and alert
      break;
    default:
      // ignore unknown events
      break;
  }

  return NextResponse.json({ received: true });
}
Để biết chi tiết về các sơ đồ payload, hãy xem Payload webhook Đăng kýPayload webhook Thanh toán.

Các Thực hành Tốt Nhất

Thực hiện các khuyến nghị này để thay đổi kế hoạch đăng ký một cách đáng tin cậy:

Chiến lược Thay đổi Kế hoạch

  • Kiểm tra kỹ lưỡng: Luôn kiểm tra các thay đổi kế hoạch trong chế độ thử nghiệm trước khi sản xuất
  • Chọn proration cẩn thận: Chọn chế độ proration phù hợp với mô hình kinh doanh của bạn
  • Xử lý các lỗi một cách nhẹ nhàng: Thực hiện xử lý lỗi đúng cách và logic thử lại
  • Giám sát tỷ lệ thành công: Theo dõi tỷ lệ thành công/thất bại của các thay đổi kế hoạch và điều tra các vấn đề

Triển khai Webhook

  • Xác minh chữ ký: Luôn xác thực chữ ký webhook để đảm bảo tính xác thực
  • Thực hiện idempotency: Xử lý các sự kiện webhook trùng lặp một cách nhẹ nhàng
  • Xử lý không đồng bộ: Đừng chặn phản hồi webhook với các thao tác nặng nề
  • Ghi lại mọi thứ: Duy trì nhật ký chi tiết để phục vụ cho việc gỡ lỗi và kiểm toán

Trải nghiệm Người dùng

  • Giao tiếp rõ ràng: Thông báo cho khách hàng về các thay đổi thanh toán và thời gian
  • Cung cấp xác nhận: Gửi email xác nhận cho các thay đổi kế hoạch thành công
  • Xử lý các trường hợp đặc biệt: Cân nhắc các giai đoạn dùng thử, proration và các khoản thanh toán không thành công
  • Cập nhật UI ngay lập tức: Phản ánh các thay đổi kế hoạch trong giao diện ứng dụng của bạn

Các Vấn đề Thường Gặp và Giải Pháp

Giải quyết các vấn đề điển hình gặp phải trong quá trình thay đổi kế hoạch đăng ký:
Triệu chứng: Cuộc gọi API thành công nhưng đăng ký vẫn ở kế hoạch cũNguyên nhân phổ biến:
  • Xử lý webhook không thành công hoặc bị trì hoãn
  • Trạng thái ứng dụng không được cập nhật sau khi nhận webhook
  • Vấn đề giao dịch cơ sở dữ liệu trong quá trình cập nhật trạng thái
Giải pháp:
  • Thực hiện xử lý webhook mạnh mẽ với logic thử lại
  • Sử dụng các thao tác idempotent cho các cập nhật trạng thái
  • Thêm giám sát để phát hiện và cảnh báo về các sự kiện webhook bị bỏ lỡ
  • Xác minh rằng điểm cuối webhook có thể truy cập và phản hồi chính xác
Triệu chứng: Khách hàng hạ cấp nhưng không thấy số dư tín dụngNguyên nhân phổ biến:
  • Kỳ vọng về chế độ proration: hạ cấp tín dụng sự khác biệt giá của toàn bộ kế hoạch với difference_immediately, trong khi prorated_immediately tạo ra một tín dụng proration dựa trên thời gian còn lại trong chu kỳ
  • Tín dụng là cụ thể cho đăng ký và không thể chuyển nhượng giữa các đăng ký
  • Số dư tín dụng không hiển thị trong bảng điều khiển của khách hàng
Giải pháp:
  • Sử dụng difference_immediately cho các hạ cấp khi bạn muốn có tín dụng tự động
  • Giải thích cho khách hàng rằng tín dụng áp dụng cho các lần gia hạn trong tương lai của cùng một đăng ký
  • Triển khai cổng thông tin khách hàng để hiển thị số dư tín dụng
  • Kiểm tra xem hóa đơn xem trước tiếp theo có tín dụng đã áp dụng hay không
Triệu chứng: Các sự kiện webhook bị từ chối do chữ ký không hợp lệNguyên nhân phổ biến:
  • Khóa bí mật webhook không chính xác
  • Nội dung yêu cầu thô đã được sửa đổi trước khi xác minh chữ ký
  • Thuật toán xác minh chữ ký sai
Giải pháp:
  • Xác minh rằng bạn đang sử dụng DODO_WEBHOOK_SECRET chính xác từ bảng điều khiển
  • Đọc nội dung yêu cầu thô trước bất kỳ middleware phân tích JSON nào
  • Sử dụng thư viện xác minh webhook tiêu chuẩn cho nền tảng của bạn
  • Thử nghiệm xác minh chữ ký webhook trong môi trường phát triển
Triệu chứng: API trả về lỗi 422 Unprocessable EntityNguyên nhân phổ biến:
  • ID đăng ký hoặc ID sản phẩm không hợp lệ
  • Đăng ký không ở trạng thái hoạt động
  • Thiếu các tham số bắt buộc
  • Sản phẩm không có sẵn cho các thay đổi kế hoạch
Giải pháp:
  • Xác minh rằng đăng ký tồn tại và đang hoạt động
  • Kiểm tra ID sản phẩm có hợp lệ và có sẵn không
  • Đảm bảo tất cả các tham số bắt buộc được cung cấp
  • Xem lại tài liệu API để biết yêu cầu tham số
Triệu chứng: Thay đổi kế hoạch đã được khởi động nhưng khoản phí ngay lập tức không thành côngNguyên nhân phổ biến:
  • Không đủ tiền trong phương thức thanh toán của khách hàng
  • Phương thức thanh toán đã hết hạn hoặc không hợp lệ
  • Ngân hàng từ chối giao dịch
  • Phát hiện gian lận đã chặn khoản phí
Giải pháp:
  • Xử lý các sự kiện webhook payment.failed một cách thích hợp
  • Thông báo cho khách hàng cập nhật phương thức thanh toán
  • Thực hiện logic thử lại cho các lỗi tạm thời
  • Cân nhắc cho phép thay đổi kế hoạch với các khoản phí ngay lập tức không thành công
Triệu chứng: Khoản phí thay đổi kế hoạch không thành công và đăng ký chuyển sang trạng thái on_holdĐiều gì xảy ra: Khi một khoản phí thay đổi kế hoạch không thành công, đăng ký sẽ tự động được đặt vào trạng thái on_hold. Đăng ký sẽ không tự động gia hạn cho đến khi phương thức thanh toán được cập nhật.Giải pháp: Cập nhật phương thức thanh toán để kích hoạt lại đăng kýĐể kích hoạt lại một đăng ký từ trạng thái on_hold sau khi thay đổi kế hoạch không thành công:
  1. Cập nhật phương thức thanh toán bằng cách sử dụng API Cập nhật Phương thức Thanh toán
  2. Tạo khoản phí tự động: API tự động tạo một khoản phí cho các khoản nợ còn lại
  3. Tạo hóa đơn: Một hóa đơn được tạo cho khoản phí
  4. Xử lý thanh toán: Thanh toán được xử lý bằng phương thức thanh toán mới
  5. Kích hoạt lại: Sau khi thanh toán thành công, đăng ký được kích hoạt lại sang trạng thái active
// Reactivate subscription from on_hold after failed plan change
async function reactivateAfterFailedPlanChange(subscriptionId) {
  // Update payment method - automatically creates charge for remaining dues
  const response = await client.subscriptions.updatePaymentMethod(subscriptionId, {
    type: 'new',
    return_url: 'https://example.com/return'
  });
  
  if (response.payment_id) {
    console.log('Charge created for remaining dues:', response.payment_id);
    console.log('Payment link:', response.payment_link);
    
    // Redirect customer to payment_link to complete payment
    // Monitor webhooks for:
    // 1. payment.succeeded - charge succeeded
    // 2. subscription.active - subscription reactivated
  }
  
  return response;
}

// Or use existing payment method if available
async function reactivateWithExistingPaymentMethod(subscriptionId, paymentMethodId) {
  const response = await client.subscriptions.updatePaymentMethod(subscriptionId, {
    type: 'existing',
    payment_method_id: paymentMethodId
  });
  
  // Monitor webhooks for payment.succeeded and subscription.active
  return response;
}
Các sự kiện webhook cần theo dõi:
  • subscription.on_hold: Đăng ký đã bị tạm dừng (nhận được khi khoản phí thay đổi kế hoạch không thành công)
  • payment.succeeded: Thanh toán cho các khoản nợ còn lại đã thành công (sau khi cập nhật phương thức thanh toán)
  • subscription.active: Đăng ký đã được kích hoạt lại sau khi thanh toán thành công
Các thực hành tốt nhất:
  • Thông báo ngay cho khách hàng khi khoản phí thay đổi kế hoạch không thành công
  • Cung cấp hướng dẫn rõ ràng về cách cập nhật phương thức thanh toán của họ
  • Giám sát các sự kiện webhook để theo dõi trạng thái kích hoạt lại
  • Cân nhắc triển khai logic thử lại tự động cho các lỗi thanh toán tạm thời

Tài liệu API Cập nhật Phương thức Thanh toán

Xem tài liệu API đầy đủ để cập nhật phương thức thanh toán và kích hoạt lại các đăng ký.

Kiểm tra Việc Triển khai của Bạn

Theo dõi các bước này để kiểm tra kỹ lưỡng việc triển khai thay đổi kế hoạch đăng ký của bạn:
1

Thiết lập môi trường thử nghiệm

  • Sử dụng khóa API thử nghiệm và các sản phẩm thử nghiệm
  • Tạo các đăng ký thử nghiệm với các loại kế hoạch khác nhau
  • Cấu hình điểm cuối webhook thử nghiệm
  • Thiết lập giám sát và ghi lại
2

Kiểm tra các chế độ proration khác nhau

  • Kiểm tra prorated_immediately với các vị trí chu kỳ thanh toán khác nhau
  • Kiểm tra difference_immediately cho các nâng cấp và hạ cấp
  • Kiểm tra full_immediately để đặt lại các chu kỳ thanh toán
  • Xác minh rằng các phép tính tín dụng là chính xác
3

Kiểm tra xử lý webhook

  • Xác minh rằng tất cả các sự kiện webhook liên quan đều được nhận
  • Kiểm tra xác minh chữ ký webhook
  • Xử lý các sự kiện webhook trùng lặp một cách nhẹ nhàng
  • Kiểm tra các kịch bản thất bại trong xử lý webhook
4

Kiểm tra các kịch bản lỗi

  • Kiểm tra với các ID đăng ký không hợp lệ
  • Kiểm tra với các phương thức thanh toán đã hết hạn
  • Kiểm tra các lỗi mạng và thời gian chờ
  • Kiểm tra với các khoản tiền không đủ
5

Giám sát trong sản xuất

  • Thiết lập cảnh báo cho các thay đổi kế hoạch không thành công
  • Giám sát thời gian xử lý webhook
  • Theo dõi tỷ lệ thành công của các thay đổi kế hoạch
  • Xem xét các vé hỗ trợ khách hàng cho các vấn đề thay đổi kế hoạch

Xử lý Lỗi

Xử lý các lỗi API phổ biến một cách nhẹ nhàng trong việc triển khai của bạn:

Mã Trạng thái HTTP

Yêu cầu thay đổi kế hoạch đã được xử lý thành công. Đăng ký đang được cập nhật và quá trình thanh toán đã bắt đầu.
Tham số yêu cầu không hợp lệ. Kiểm tra rằng tất cả các trường bắt buộc đã được cung cấp và định dạng đúng.
Khóa API không hợp lệ hoặc thiếu. Xác minh rằng DODO_PAYMENTS_API_KEY của bạn là chính xác và có quyền truy cập phù hợp.
ID đăng ký không được tìm thấy hoặc không thuộc về tài khoản của bạn.
Đăng ký không thể được thay đổi (ví dụ: đã bị hủy, sản phẩm không có sẵn, v.v.).
Đã xảy ra lỗi máy chủ. Thử lại yêu cầu sau một khoảng thời gian ngắn.

Định dạng Phản hồi Lỗi

{
  "error": {
    "code": "subscription_not_found",
    "message": "The subscription with ID 'sub_123' was not found",
    "details": {
      "subscription_id": "sub_123"
    }
  }
}

Các bước tiếp theo