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

Tổng quan

Đăng ký theo yêu cầu cho phép bạn ủy quyền phương thức thanh toán của khách hàng một lần và sau đó tính phí các khoản biến đổi bất cứ khi nào bạn cần, thay vì theo lịch trình cố định.
Tính năng này có thể cần được kích hoạt trên tài khoản của bạn. Liên hệ với bộ phận hỗ trợ nếu bạn không thấy nó trong bảng điều khiển của mình.
Sử dụng hướng dẫn này để:
  • Tạo một đăng ký theo yêu cầu (ủy quyền một mệnh lệnh với giá ban đầu tùy chọn)
  • Kích hoạt các khoản phí tiếp theo với số tiền tùy chỉnh
  • Theo dõi kết quả bằng cách sử dụng webhook
Để thiết lập đăng ký chung, xem Hướng dẫn tích hợp Đăng ký.

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

  • Tài khoản thương nhân Dodo Payments và khóa API
  • Bí mật webhook được cấu hình và một điểm cuối để nhận sự kiện
  • Một sản phẩm đăng ký trong danh mục của bạn
Nếu bạn muốn khách hàng phê duyệt mệnh lệnh qua thanh toán được lưu trữ, hãy đặt payment_link: true và cung cấp một return_url.

Cách thức hoạt động của đăng ký theo yêu cầu

  1. Bạn tạo một đăng ký với đối tượng on_demand để ủy quyền một phương thức thanh toán và tùy chọn thu phí ban đầu.
  2. Sau đó, bạn tạo các khoản phí chống lại đăng ký đó với số tiền tùy chỉnh bằng cách sử dụng điểm cuối phí chuyên dụng.
  3. Bạn lắng nghe các webhook (ví dụ: payment.succeeded, payment.failed) để cập nhật hệ thống của bạn.

Tạo một đăng ký theo yêu cầu

Điểm cuối: POST /subscriptions Các trường yêu cầu chính (nội dung):
product_id
string
required
ID sản phẩm cho đăng ký.
quantity
integer
required
Số lượng đơn vị. Tối thiểu 1.
billing
object
required
Địa chỉ thanh toán cho khách hàng.
customer
object
required
Gắn một khách hàng hiện có hoặc cung cấp thông tin chi tiết của khách hàng.
Nếu đúng, tạo một liên kết thanh toán được lưu trữ cho việc ủy quyền mệnh lệnh và thanh toán ban đầu tùy chọn.
return_url
string
Nơi để chuyển hướng khách hàng sau khi hoàn tất thanh toán được lưu trữ.
on_demand.mandate_only
boolean
required
Nếu đúng, ủy quyền phương thức thanh toán mà không tính phí cho khách hàng trong quá trình tạo.
on_demand.product_price
integer
Số tiền phí ban đầu (tính bằng đơn vị tiền tệ nhỏ nhất). Nếu được chỉ định, giá trị này sẽ ghi đè lên giá gốc của sản phẩm được thiết lập trong quá trình tạo sản phẩm. Nếu bị bỏ qua, giá đã lưu của sản phẩm sẽ được sử dụng. Ví dụ: để tính phí $1.00, hãy truyền 100.
on_demand.product_currency
string
Ghi đè tiền tệ tùy chọn cho phí ban đầu. Mặc định là tiền tệ của sản phẩm.
on_demand.product_description
string
Ghi đè mô tả tùy chọn cho việc thanh toán và các mục dòng.
on_demand.adaptive_currency_fees_inclusive
boolean
Nếu đúng, bao gồm phí tiền tệ thích ứng trong product_price. Nếu sai, phí sẽ được thêm vào. Bị bỏ qua khi giá thích ứng bị vô hiệu hóa.

Tạo một đăng ký theo yêu cầu

import DodoPayments from 'dodopayments';

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

async function main() {
  const subscription = await client.subscriptions.create({
    billing: { city: 'SF', country: 'US', state: 'CA', street: '1 Market St', zipcode: '94105' },
    customer: { customer_id: 'customer_123' },
    product_id: 'prod_sub_123',
    quantity: 1,
    payment_link: true,
    return_url: 'https://example.com/billing/success',
    on_demand: {
      mandate_only: true, // set false to collect an initial charge
      // product_price: 1000, // optional: charge $10.00 now if mandate_only is false
      // product_currency: 'USD',
      // product_description: 'Custom initial charge',
      // adaptive_currency_fees_inclusive: false,
    },
  });

  // If payment_link was true, redirect the customer to authorize the mandate
  console.log(subscription.payment_link);
}

main().catch(console.error);
Đặt payment_link: true, chuyển hướng khách hàng đến payment_link để hoàn tất việc ủy quyền mệnh lệnh.
Success
{
  "subscription_id": "sub_123",
  "payment_link": "https://pay.dodopayments.com/checkout/...",
  "customer": { "customer_id": "customer_123", "email": "[email protected]", "name": "Alex Doe" },
  "metadata": {},
  "recurring_pre_tax_amount": 0,
  "addons": []
}

Tính phí cho một đăng ký theo yêu cầu

Sau khi mệnh lệnh được ủy quyền, tạo các khoản phí khi cần. Điểm cuối: POST /subscriptions/{subscription_id}/charge Các trường yêu cầu chính (nội dung):
product_price
integer
required
Số tiền để tính phí (tính bằng đơn vị tiền tệ nhỏ nhất). Ví dụ: để tính phí $25.00, hãy truyền 2500.
product_currency
string
Ghi đè tiền tệ tùy chọn cho khoản phí.
product_description
string
Ghi đè mô tả tùy chọn cho khoản phí này.
adaptive_currency_fees_inclusive
boolean
Nếu đúng, bao gồm phí tiền tệ thích ứng trong product_price. Nếu sai, phí sẽ được thêm vào.
metadata
object
Thông tin bổ sung cho khoản thanh toán. Nếu bị bỏ qua, thông tin đăng ký sẽ được sử dụng.
import DodoPayments from 'dodopayments';

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

async function chargeNow(subscriptionId) {
  const res = await client.subscriptions.charge(subscriptionId, { product_price: 2500 });
  console.log(res.payment_id);
}

chargeNow('sub_123').catch(console.error);
Success
{ "payment_id": "pay_abc123" }
Tính phí cho một đăng ký không phải theo yêu cầu có thể thất bại. Đảm bảo rằng đăng ký có on_demand: true trong chi tiết của nó trước khi tính phí.

Thử lại thanh toán

Hệ thống phát hiện gian lận của chúng tôi có thể chặn các mẫu thử lại mạnh mẽ (và có thể đánh dấu chúng là thử nghiệm thẻ tiềm năng). Tuân theo một chính sách thử lại an toàn.
Các mẫu thử lại bùng nổ có thể bị đánh dấu là gian lận hoặc thử nghiệm thẻ nghi ngờ bởi các hệ thống và bộ xử lý rủi ro của chúng tôi. Tránh các thử lại cụm; tuân theo lịch trình lùi và hướng dẫn căn thời gian bên dưới.

Nguyên tắc cho các chính sách thử lại an toàn

  • Cơ chế lùi: Sử dụng lùi theo cấp số nhân giữa các lần thử lại.
  • Giới hạn thử lại: Giới hạn tổng số lần thử lại (tối đa 3–4 lần).
  • Lọc thông minh: Chỉ thử lại khi gặp lỗi có thể thử lại (ví dụ: lỗi mạng/nhà phát hành, không đủ tiền); không bao giờ thử lại các từ chối cứng.
  • Ngăn chặn thử nghiệm thẻ: Không thử lại các lỗi như DO_NOT_HONOR, STOLEN_CARD, LOST_CARD, PICKUP_CARD, FRAUDULENT, AUTHENTICATION_FAILURE.
  • Thay đổi metadata (tùy chọn): Nếu bạn duy trì hệ thống thử lại của riêng mình, phân biệt các lần thử lại qua metadata (ví dụ: retry_attempt).

Lịch trình thử lại đề xuất (đăng ký)

  • Lần thử lại đầu tiên: Ngay lập tức khi bạn tạo khoản phí
  • Lần thử lại thứ hai: Sau 3 ngày
  • Lần thử lại thứ ba: Sau 7 ngày nữa (tổng cộng 10 ngày)
  • Lần thử lại thứ tư (cuối cùng): Sau 7 ngày nữa (tổng cộng 17 ngày)
Bước cuối cùng: nếu vẫn chưa thanh toán, đánh dấu đăng ký là chưa thanh toán hoặc hủy nó, dựa trên chính sách của bạn. Thông báo cho khách hàng trong khoảng thời gian để cập nhật phương thức thanh toán của họ.

Tránh các thử lại bùng nổ; căn chỉnh theo thời gian ủy quyền

  • Gắn các lần thử lại vào dấu thời gian ủy quyền ban đầu để tránh hành vi “bùng nổ” trên toàn bộ danh mục của bạn.
  • Ví dụ: Nếu khách hàng bắt đầu một thử nghiệm hoặc mệnh lệnh vào lúc 1:10 chiều hôm nay, hãy lên lịch các lần thử lại tiếp theo vào lúc 1:10 chiều trong các ngày tiếp theo theo lịch lùi của bạn (ví dụ: +3 ngày → 1:10 chiều, +7 ngày → 1:10 chiều).
  • Ngoài ra, nếu bạn lưu thời gian thanh toán thành công cuối cùng T, hãy lên lịch lần thử tiếp theo vào T + X days để duy trì sự căn chỉnh theo thời gian trong ngày.
Múi giờ và DST: sử dụng một tiêu chuẩn thời gian nhất quán cho việc lập lịch và chuyển đổi chỉ để hiển thị nhằm duy trì các khoảng thời gian.

Mã từ chối bạn không nên thử lại

  • STOLEN_CARD
  • DO_NOT_HONOR
  • FRAUDULENT
  • PICKUP_CARD
  • AUTHENTICATION_FAILURE
  • LOST_CARD
Để có danh sách đầy đủ các lý do từ chối và liệu chúng có thể được sửa chữa bởi người dùng hay không, hãy xem tài liệu Transaction Failures.
Chỉ thử lại khi gặp các vấn đề mềm/tạm thời (ví dụ: insufficient_funds, issuer_unavailable, processing_error, thời gian chờ mạng). Nếu cùng một từ chối lặp lại, hãy tạm dừng các lần thử lại tiếp theo.

Hướng dẫn triển khai (không có mã)

  • Sử dụng một bộ lập lịch/ hàng đợi mà duy trì các dấu thời gian chính xác; tính toán lần thử tiếp theo tại thời điểm chính xác (ví dụ: T + 3 days vào cùng một HH:MM).
  • Duy trì và tham chiếu dấu thời gian thanh toán thành công cuối cùng T để tính toán lần thử tiếp theo; không gom nhiều đăng ký vào cùng một thời điểm.
  • Luôn đánh giá lý do từ chối cuối cùng; dừng thử lại cho các từ chối cứng trong danh sách bỏ qua ở trên.
  • Giới hạn số lần thử lại đồng thời theo khách hàng và theo tài khoản để ngăn chặn các đợt tăng đột biến không mong muốn.
  • Giao tiếp chủ động: gửi email/SMS cho khách hàng để cập nhật phương thức thanh toán của họ trước lần thử tiếp theo đã lên lịch.
  • Sử dụng metadata chỉ để quan sát (ví dụ: retry_attempt); không bao giờ cố gắng “tránh” các hệ thống gian lận/rủi ro bằng cách xoay vòng các trường không quan trọng.

Theo dõi kết quả với webhook

Triển khai xử lý webhook để theo dõi hành trình của khách hàng. Xem Triển khai Webhooks.
  • subscription.active: Mệnh lệnh đã được ủy quyền và đăng ký đã được kích hoạt
  • subscription.failed: Tạo không thành công (ví dụ: thất bại mệnh lệnh)
  • subscription.on_hold: Đăng ký bị tạm hoãn (ví dụ: trạng thái chưa thanh toán)
  • payment.succeeded: Tính phí thành công
  • payment.failed: Tính phí thất bại
Đối với các luồng theo yêu cầu, tập trung vào payment.succeededpayment.failed để đối chiếu các khoản phí dựa trên mức sử dụng.

Kiểm tra và các bước tiếp theo

1

Tạo trong chế độ thử nghiệm

Sử dụng khóa API thử nghiệm của bạn để tạo đăng ký với payment_link: true, sau đó mở liên kết và hoàn tất mệnh lệnh.
2

Kích hoạt một khoản phí

Gọi điểm cuối phí với một product_price nhỏ (ví dụ: 100) và xác minh rằng bạn nhận được payment.succeeded.
3

Đi vào hoạt động

Chuyển sang khóa API trực tiếp của bạn khi bạn đã xác thực các sự kiện và cập nhật trạng thái nội bộ.

Khắc phục sự cố

  • 422 Yêu cầu không hợp lệ: Đảm bảo on_demand.mandate_only được cung cấp khi tạo và product_price được cung cấp cho các khoản phí.
  • Lỗi tiền tệ: Nếu bạn ghi đè product_currency, xác nhận rằng nó được hỗ trợ cho tài khoản và khách hàng của bạn.
  • Không nhận được webhook: Xác minh URL webhook và cấu hình bí mật chữ ký.