Langsung ke konten utama

Documentation Index

Fetch the complete documentation index at: https://docs.dodopayments.com/llms.txt

Use this file to discover all available pages before exploring further.

Change Plan API

Full API docs for updating subscriptions.

Plan Change Preview

See charge amounts before changing plans.

Integration Guide

Step-by-step subscription setup.

What is a subscription upgrade or downgrade?

Changing plans lets you move a customer between subscription tiers or quantities. Use it to:
  • Align pricing with usage or features
  • Move from monthly to annual (or vice versa)
  • Adjust quantity for seat-based products
Plan changes can trigger an immediate charge depending on the proration mode you choose.

When to use plan changes

  • Upgrade when a customer needs more features, usage, or seats
  • Downgrade when usage decreases
  • Migrate users to a new product or price without cancelling their subscription

Plan Change Flow

Prerequisites

Before implementing subscription plan changes, ensure you have:
  • A Dodo Payments merchant account with active subscription products
  • API credentials (API key and webhook secret key) from the dashboard
  • An existing active subscription to modify
  • Webhook endpoint configured to handle subscription events
For detailed setup instructions, see our Integration Guide.

Step-by-Step Implementation Guide

Follow this comprehensive guide to implement subscription plan changes in your application:
1

Understand Plan Change Requirements

Before implementing, determine:
  • Which subscription products can be changed to which others
  • What proration mode fits your business model
  • How to handle failed plan changes gracefully
  • Which webhook events to track for state management
Test plan changes thoroughly in test mode before implementing in production.
2

Choose Your Proration Strategy

Select the billing approach that aligns with your business needs:
Best for: SaaS applications wanting to charge fairly for unused time
  • Calculates exact prorated amount based on remaining cycle time
  • Charges a prorated amount based on unused time remaining in the cycle
  • Provides transparent billing to customers
3

Implement the Change Plan API

Use the Change Plan API to modify subscription details:
subscription_id
string
wajib
The ID of the active subscription to modify.
product_id
string
wajib
The new product ID to change the subscription to.
quantity
integer
default:"1"
Number of units for the new plan (for seat-based products).
proration_billing_mode
string
wajib
How to handle immediate billing: prorated_immediately, full_immediately, difference_immediately, or do_not_bill.
addons
array
Optional addons for the new plan. Leaving this empty removes any existing addons.
on_payment_failure
string
Controls behavior when the plan change payment fails:
  • prevent_change: Keep subscription on current plan until payment succeeds
  • apply_change (default): Apply plan change immediately regardless of payment outcome
If not specified, uses the business-level default setting.
discount_codes
array
Kode diskon tambahan opsional untuk diterapkan ke paket baru (maks 20, diterapkan dalam urutan array). Perilaku tergantung pada apa yang Anda berikan:
  • Tidak disediakan / null — diskon yang ada dengan preserve_on_plan_change=true dipertahankan jika berlaku untuk produk baru.
  • [] (array kosong) — menghapus semua diskon yang ada dari langganan.
  • ["CODE_A", "CODE_B", ...] — menggantikan diskon yang ada dengan set baru ini.
discount_code
string
usang
Dihapus — lebih memilih discount_codes untuk integrasi baru. Bidang ini masih berfungsi untuk kompatibilitas ke belakang, tetapi tidak dapat digabungkan dengan discount_codes dalam permintaan yang sama.
effective_at
string
default:"immediately"
Kapan mengajukan perubahan paket:
  • immediately (default): Terapkan segera perubahan paket
  • next_billing_date: Jadwalkan perubahan untuk tanggal penagihan berikutnya. Pelanggan mempertahankan paket mereka saat ini hingga periode penagihan berakhir.
Gunakan next_billing_date untuk penurunan versi sehingga pelanggan tetap mendapatkan manfaat paket mereka saat ini hingga akhir periode penagihan.
4

Handle Webhook Events

Mengatur penanganan webhook untuk melacak hasil perubahan paket:
  • subscription.active: Perubahan paket berhasil, langganan diperbarui
  • subscription.plan_changed: Paket langganan berubah (peningkatan/penurunan versi/pembaruan addon)
  • subscription.on_hold: Biaya perubahan paket gagal, langganan dijeda
  • payment.succeeded: Biaya langsung untuk perubahan paket berhasil
  • payment.failed: Biaya langsung gagal
Selalu verifikasi tanda tangan webhook dan terapkan pemrosesan acara idempoten.
5

Update Your Application State

Berdasarkan acara webhook, perbarui aplikasi Anda:
  • Berikan/cabut fitur berdasarkan paket baru
  • Perbarui dasbor pelanggan dengan detail paket baru
  • Kirim email konfirmasi tentang perubahan paket
  • Catat perubahan penagihan untuk tujuan audit
6

Test and Monitor

Uji implementasi Anda secara menyeluruh:
  • Uji semua mode proratasi dengan berbeda skenario
  • Verifikasi penanganan webhook berfungsi dengan benar
  • Monitor tingkat keberhasilan perubahan paket
  • Siapkan peringatan untuk perubahan paket yang gagal
Implementasi perubahan paket langganan Anda sekarang siap untuk digunakan produksi.

Pratinjau Perubahan Paket

Sebelum melakukan perubahan paket, gunakan Preview API untuk menunjukkan kepada pelanggan berapa tepatnya yang akan mereka bayar:
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);
Gunakan API pratinjau untuk membuat dialog konfirmasi yang menunjukkan kepada pelanggan jumlah tepat yang akan mereka bayar sebelum mereka mengonfirmasi perubahan paket.

API Perubahan Paket

Gunakan API Perubahan Paket untuk memodifikasi produk, kuantitas, dan perilaku proratasi untuk langganan aktif.

Contoh cepat memulai

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',
    on_payment_failure: 'prevent_change', // Optional: control behavior on payment failure
  });
  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"
}
Fields seperti invoice_id dan payment_id hanya dikembalikan ketika biaya langsung dan/atau faktur dibuat selama perubahan paket. Selalu andalkan acara webhook (misalnya, payment.succeeded, subscription.plan_changed) untuk mengonfirmasi hasil.
Jika biaya langsung gagal, langganan mungkin berpindah ke subscription.on_hold hingga pembayaran berhasil.

Mengelola Addon

Saat mengubah paket langganan, Anda juga dapat memodifikasi 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
});
Addon termasuk dalam perhitungan proratasi dan akan dikenakan biaya sesuai dengan mode proratasi yang dipilih.

Menerapkan Kode Diskon

Anda dapat menerapkan satu atau lebih kode diskon tambahan saat mengubah paket langganan (maks 20, diterapkan dalam urutan array). Ini berguna untuk menawarkan harga promosi pada peningkatan atau migrasi.
// Apply stacked discount codes during plan change
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_pro',
  quantity: 1,
  proration_billing_mode: 'prorated_immediately',
  discount_codes: ['UPGRADE20']
});

Perilaku diskon pada perubahan paket

Nilai discount_codesPerilaku
Tidak disediakan / nullDiskon yang ada dengan preserve_on_plan_change=true secara otomatis dipertahankan jika berlaku untuk produk baru.
[] (array kosong)Semua diskon yang ada dihapus dari langganan.
["CODE_A", "CODE_B", ...]Menggantikan diskon yang ada dengan set tambahan ini, divalidasi dan diterapkan dalam urutan array.
Bidang tunggal discount_code di endpoint ini dihapus tetapi masih berfungsi untuk kompatibilitas ke belakang — integrasi yang ada tidak perlu mengubah segera. Tidak dapat digabungkan dengan discount_codes dalam permintaan yang sama. Migrasikan ke bentuk array saat nyaman.
Gunakan Preview Plan Change API dengan discount_codes untuk menunjukkan kepada pelanggan berapa banyak yang akan mereka hemat sebelum mengonfirmasi perubahan paket.

Mode Prorasi

Pilih cara untuk menagih pelanggan saat mengubah paket:

prorated_immediately

  • Menagih perbedaan parsial dalam siklus saat ini
  • Jika dalam percobaan, langsung menagih dan beralih ke paket baru sekarang
  • Penurunan versi: dapat menghasilkan kredit prorated yang diterapkan ke pembaruan mendatang

full_immediately

  • Menagih jumlah penuh dari paket baru secara langsung
  • Mengabaikan waktu yang tersisa dari paket lama
Kredit yang dibuat oleh penurunan versi menggunakan difference_immediately diterapkan pada ruang lingkup langganan dan berbeda dari hak Penagihan Berbasis Kredit. Mereka secara otomatis diaplikasikan pada pembaruan di masa mendatang dari langganan yang sama dan tidak dapat dipindahtangankan antara langganan.

difference_immediately

  • Peningkatan: langsung menagih perbedaan harga antara paket lama dan baru
  • Penurunan versi: tambahkan nilai yang tersisa sebagai kredit internal pada langganan dan terapkan secara otomatis saat pembaruan

do_not_bill

  • Tidak ada biaya atau kredit yang dihitung
  • Pelanggan beralih ke paket baru segera tanpa penyesuaian penagihan
  • Siklus penagihan tetap tidak berubah
  • Terbaik untuk migrasi sopan santun, perpindahan paket gratis, atau menyerap perbedaan biaya
Fiturprorated_immediatelydifference_immediatelyfull_immediatelydo_not_bill
Biaya PeningkatanPerbedaan yang sesuai untuk hari yang tersisaHarga penuh beda antara paketHarga penuh paket baruTidak ada biaya
Kredit Penurunan versiKredit prorated untuk hari yang tersisaPerbedaan harga penuh sebagai kreditTidak ada kreditTidak ada kredit
Siklus PenagihanTidak berubahTidak berubahDiatur ulang ke hari iniTidak berubah
Perilaku PercobaanMengakhiri percobaan, menagih segeraMengakhiri percobaan, menagih segeraMengakhiri percobaan, menagih jumlah penuhMengakhiri percobaan, tidak ada biaya
Terbaik untukPenagihan berbasis waktu yang adilMatematika peningkatan/penurunan versi sederhanaMengatur ulang siklus penagihanMigrasi gratis atau perubahan sopan santun
KompleksitasSedang (perhitungan hari)Rendah (pengurangan sederhana)Rendah (biaya penuh)Tidak ada

Contoh skenario

Gunakan angka kanonik ini secara konsisten:
  • Paket saat ini: Basic di $30/bulan
  • Target peningkatan: Pro di $80/bulan
  • Target penurunan (dari Pro): Starter di $20/bulan
  • Siklus penagihan: 30 hari, dimulai pada 1 Januari
  • Perubahan paket terjadi pada 16 Januari (15 hari tersisa, 15 hari digunakan)
Step 1: Calculate unused credit from current plan
  Unused days = 15 out of 30 days
  Credit = $30 × (15/30) = $15.00

Step 2: Calculate prorated cost of new plan
  Remaining days = 15 out of 30 days
  New plan cost = $80 × (15/30) = $40.00

Step 3: Calculate immediate charge
  Charge = New plan cost − Credit
  Charge = $40.00 − $15.00 = $25.00

→ Customer pays $25.00 now
→ Next renewal (Feb 1): $80.00/month
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_pro',
  quantity: 1,
  proration_billing_mode: 'prorated_immediately'
})
Step 1: Calculate unused credit from current plan
  Unused days = 15 out of 30 days
  Credit = $80 × (15/30) = $40.00

Step 2: Calculate prorated cost of new plan
  Remaining days = 15 out of 30 days
  New plan cost = $20 × (15/30) = $10.00

Step 3: Calculate credit balance
  Credit = $40.00 − $10.00 = $30.00

→ No charge — $30.00 credit added to subscription
→ Credit auto-applies to future renewals
→ Next renewal (Feb 1): $20.00 − $30.00 credit = $0.00
→ Following renewal (Mar 1): $20.00 − $10.00 remaining credit = $10.00
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_starter',
  quantity: 1,
  proration_billing_mode: 'prorated_immediately'
})
Immediate charge = New plan price − Old plan price
                 = $80 − $30
                 = $50.00

→ Customer pays $50.00 now (regardless of cycle position)
→ Next renewal (Feb 1): $80.00/month
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_pro',
  quantity: 1,
  proration_billing_mode: 'difference_immediately'
})
Credit = Old plan price − New plan price
       = $80 − $20
       = $60.00

→ No charge — $60.00 credit added to subscription
→ Credit auto-applies to future renewals
→ Next renewal: $20.00 − $20.00 (from credit) = $0.00
→ Following renewal: $20.00 − $20.00 (from credit) = $0.00
→ Third renewal: $20.00 − $20.00 (from remaining credit) = $0.00
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_starter',
  quantity: 1,
  proration_billing_mode: 'difference_immediately'
})
Immediate charge = Full new plan price = $80.00

→ Customer pays $80.00 now
→ No credit for unused time on old plan
→ Billing cycle resets to today (January 16)
→ Next renewal: February 16 at $80.00/month
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_pro',
  quantity: 1,
  proration_billing_mode: 'full_immediately'
})
Current: Basic plan ($30/month), no add-ons
New: Pro plan ($80/month) + Extra Seats add-on ($10/seat × 3 seats = $30/month)
Change on day 16 of 30 (15 days remaining)

Step 1: Credit from current plan
  Credit = $30 × (15/30) = $15.00

Step 2: Prorated cost of new plan + add-ons
  New plan = $80 × (15/30) = $40.00
  Add-ons = $30 × (15/30) = $15.00
  Total new = $55.00

Step 3: Immediate charge
  Charge = $55.00 − $15.00 = $40.00

→ Customer pays $40.00 now
→ Next renewal: $80.00 + $30.00 = $110.00/month
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_pro',
  quantity: 1,
  proration_billing_mode: 'prorated_immediately',
  addons: [
    { addon_id: 'addon_seats', quantity: 3 }
  ]
})

Bagaimana setiap mode memproses penagihan

Pilih prorated_immediately untuk perhitungan waktu yang adil; pilih full_immediately untuk memulai ulang penagihan; gunakan difference_immediately untuk peningkatan sederhana dan kredit otomatis pada penurunan versi; atau gunakan do_not_bill untuk mengganti paket tanpa penyesuaian penagihan.

Penanganan Kegagalan Pembayaran

Kontrol apa yang terjadi ketika pembayaran perubahan paket gagal menggunakan parameter on_payment_failure.

Mode Kegagalan Pembayaran

Jika tidak ditentukan, parameter on_payment_failure menggunakan pengaturan default tingkat bisnis Anda yang dikonfigurasi di dasbor.

Kapan Menggunakan Setiap Mode

SkenarioMode yang DirekomendasikanAlasan
Meningkatkan ke fitur premiumprevent_changePastikan pembayaran sebelum memberikan akses
Peningkatan jumlah (lebih banyak kursi)prevent_changeMencegah penggunaan tanpa pembayaran
Menurunkan paketapply_changePelanggan mengurangi pengeluaran
Pelanggan perusahaan terpercayaapply_changeRisiko lebih rendah dari ketidakpembayaran
Konversi percobaan ke berbayarprevent_changeMomen pembayaran kritis

Penanganan webhooks

Melacak status langganan melalui webhook untuk mengonfirmasi perubahan paket dan pembayaran.

Jenis acara yang ditangani

  • subscription.active: langganan diaktifkan
  • subscription.plan_changed: paket langganan berubah (peningkatan/penurunan versi/perubahan addon)
  • subscription.on_hold: biaya gagal, langganan dijeda
  • subscription.renewed: pembaruan berhasil
  • payment.succeeded: pembayaran untuk perubahan paket atau pembaruan berhasil
  • payment.failed: pembayaran gagal
Kami merekomendasikan menggerakkan logika bisnis dari acara langganan dan menggunakan acara pembayaran untuk konfirmasi dan rekonsiliasi.

Memverifikasi tanda tangan dan menangani niat

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 });
}
Untuk skema payload rinci, lihat Payload webhook langganan dan Payload webhook pembayaran.

Praktik Terbaik

Ikuti rekomendasi ini untuk perubahan paket langganan yang andal:

Strategi Perubahan Paket

  • Uji secara menyeluruh: Selalu uji perubahan paket dalam modus percobaan sebelum produksi
  • Pilih proratasi dengan hati-hati: Pilih mode proratasi yang sesuai dengan model bisnis Anda
  • Tangani kegagalan dengan anggun: Terapkan penanganan kesalahan yang tepat dan logika pengulangan
  • Monitor tingkat keberhasilan: Lacak tingkat keberhasilan/kegagalan perubahan paket dan teliti masalah

Implementasi Webhook

  • Verifikasi tanda tangan: Selalu validasi tanda tangan webhook untuk memastikan keaslian
  • Terapkan idempoten: Tangani acara webhook duplikat dengan anggun
  • Proses secara asynchronous: Jangan memblokir tanggapan webhook dengan operasi berat
  • Catat semuanya: Pertahankan catatan rinci untuk debugging dan tujuan audit

Pengalaman Pengguna

  • Komunikasikan dengan jelas: Informasikan pelanggan tentang perubahan penagihan dan waktu
  • Berikan konfirmasi: Kirim email konfirmasi untuk perubahan paket yang berhasil
  • Tangani kasus tepi: Pertimbangkan periode percobaan, prorasi, dan pembayaran yang gagal
  • Perbarui antarmuka pengguna segera: Cerminkan perubahan paket dalam antarmuka aplikasi Anda

Masalah Umum dan Solusi

Selesaikan masalah umum yang ditemui selama perubahan paket langganan:
Gejala: Panggilan API berhasil tetapi langganan tetap pada paket lamaPenyebab umum:
  • Pemrosesan webhook gagal atau tertunda
  • Status aplikasi tidak diperbarui setelah menerima webhook
  • Masalah transaksi database selama pembaruan status
Solusi:
  • Terapkan penanganan webhook yang kuat dengan logika pengulangan
  • Gunakan operasi idempoten untuk pembaruan status
  • Tambahkan pemantauan untuk mendeteksi dan memberi peringatan tentang acara webhook yang terlewat
  • Verifikasi endpoint webhook dapat diakses dan merespons dengan benar
Gejala: Pelanggan menurunkan versi tetapi tidak melihat saldo kreditPenyebab umum:
  • Ekspektasi mode proratasi: penurunan kredit harga penuh paket dengan difference_immediately, sementara prorated_immediately menciptakan kredit prorated berdasarkan waktu yang tersisa dalam siklus
  • Kredit bersifat spesifik untuk langganan dan tidak berlaku untuk langganan lain
  • Saldo kredit tidak terlihat di dasbor pelanggan
Solusi:
  • Gunakan difference_immediately untuk penurunan jika Anda menginginkan kredit otomatis
  • Jelaskan kepada pelanggan bahwa kredit berlaku untuk pembaruan masa depan dari langganan yang sama
  • Terapkan portal pelanggan untuk menampilkan saldo kredit
  • Periksa pratinjau faktur berikutnya untuk melihat kredit yang diterapkan
Gejala: Acara webhook ditolak karena tanda tangan tidak sahPenyebab umum:
  • Kunci rahasia webhook yang salah
  • Tubuh permintaan mentah dimodifikasi sebelum verifikasi tanda tangan
  • Algoritma verifikasi tanda tangan yang salah
Solusi:
  • Verifikasi bahwa Anda menggunakan DODO_WEBHOOK_SECRET yang benar dari dasbor
  • Baca tubuh permintaan mentah sebelum middleware parsing JSON
  • Gunakan perpustakaan verifikasi webhook standar untuk platform Anda
  • Uji verifikasi tanda tangan webhook di lingkungan pengembangan
Gejala: API mengembalikan kesalahan 422 Unprocessable EntityPenyebab umum:
  • ID langganan tidak valid atau ID produk
  • Langganan tidak dalam status aktif
  • Parameter yang dibutuhkan hilang
  • Produk tidak tersedia untuk perubahan paket
Solusi:
  • Verifikasi bahwa langganan ada dan aktif
  • Periksa ID produk valid dan tersedia
  • Pastikan semua parameter yang dibutuhkan diberikan
  • Tinjau dokumentasi API untuk persyaratan parameter
Gejala: Perubahan paket dimulai tetapi biaya langsung gagalPenyebab umum:
  • Dana tidak mencukupi pada metode pembayaran pelanggan
  • Metode pembayaran kadaluarsa atau tidak valid
  • Bank menolak transaksi
  • Deteksi penipuan memblokir biaya
Solusi:
  • Tangani acara webhook payment.failed dengan tepat
  • Notifikasi pelanggan untuk memperbarui metode pembayaran
  • Terapkan logika pengulangan untuk kegagalan sementara
  • Pertimbangkan untuk mengizinkan perubahan paket dengan biaya langsung yang gagal
Gejala: Biaya perubahan paket gagal dan langganan berpindah ke status on_holdApa yang terjadi: Ketika biaya perubahan paket gagal, langganan secara otomatis ditempatkan dalam status on_hold. Langganan tidak akan diperpanjang secara otomatis hingga metode pembayaran diperbarui.Solusi: Perbarui metode pembayaran untuk mengaktifkan kembali langgananUntuk mengaktifkan kembali langganan dari status on_hold setelah perubahan paket gagal:
  1. Perbarui metode pembayaran menggunakan Update Payment Method API
  2. Pembuatan biaya otomatis: API secara otomatis membuat biaya untuk jumlah yang belum dibayar
  3. Pembuatan faktur: Faktur dibuat untuk biaya
  4. Pemrosesan pembayaran: Pembayaran diproses menggunakan metode pembayaran baru
  5. Reaktivasi: Setelah pembayaran berhasil, langganan diaktifkan kembali ke status 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;
}
Acara webhook untuk dipantau:
  • subscription.on_hold: Langganan di tempat tahan (diterima ketika biaya perubahan paket gagal)
  • payment.succeeded: Pembayaran untuk jumlah yang tertunda berhasil (setelah memperbarui metode pembayaran)
  • subscription.active: Langganan diaktifkan kembali setelah pembayaran berhasil
Praktik terbaik:
  • Notifikasi pelanggan segera ketika biaya perubahan paket gagal
  • Berikan instruksi yang jelas tentang cara memperbarui metode pembayaran mereka
  • Pantau acara webhook untuk melacak status reaktivasi
  • Pertimbangkan untuk menerapkan logika pengulangan otomatis untuk kegagalan pembayaran sementara

Update Payment Method API Reference

Lihat dokumentasi API lengkap untuk memperbarui metode pembayaran dan mengaktifkan kembali langganan.

Menguji Implementasi Anda

Ikuti langkah-langkah ini untuk menguji implementasi perubahan paket langganan Anda secara menyeluruh:
1

Set up test environment

  • Gunakan kunci API uji dan produk uji
  • Buat langganan uji dengan berbagai jenis paket
  • Konfigurasi endpoint webhook uji
  • Siapkan pemantauan dan pencatatan
2

Test different proration modes

  • Uji prorated_immediately dengan berbagai posisi siklus penagihan
  • Uji difference_immediately untuk peningkatan dan penurunan versi
  • Uji full_immediately untuk mengatur ulang siklus penagihan
  • Uji do_not_bill untuk perubahan paket tanpa biaya/kredit
  • Verifikasi perhitungan kredit benar
3

Test webhook handling

  • Verifikasi semua acara webhook yang relevan diterima
  • Uji verifikasi tanda tangan webhook
  • Tangani acara webhook duplikat dengan anggun
  • Uji skenario kegagalan pemrosesan webhook
4

Test error scenarios

  • Uji dengan ID langganan yang tidak valid
  • Uji dengan metode pembayaran yang kedaluwarsa
  • Uji kegagalan jaringan dan waktu tunggu
  • Uji dengan dana tidak mencukupi
5

Monitor in production

  • Siapkan peringatan untuk perubahan paket yang gagal
  • Monitor waktu pemrosesan webhook
  • Lacak tingkat keberhasilan perubahan paket
  • Tinjau tiket dukungan pelanggan untuk masalah perubahan paket

Penanganan Kesalahan

Tangani kesalahan API umum dengan baik dalam implementasi Anda:

Kode Status HTTP

Permintaan perubahan paket diproses dengan sukses. Langganan sedang diperbarui dan pemrosesan pembayaran telah dimulai.
Parameter permintaan tidak valid. Periksa apakah semua bidang yang dibutuhkan disediakan dan diformat dengan benar.
API key tidak valid atau hilang. Verifikasi bahwa DODO_PAYMENTS_API_KEY Anda benar dan memiliki izin yang tepat.
ID langganan tidak ditemukan atau tidak milik akun Anda.
Langganan tidak dapat diubah (misalnya, sudah dibatalkan, produk tidak tersedia, dll.).
Kesalahan server terjadi. Coba kembali permintaan setelah penundaan singkat.

Format Tanggapan Kesalahan

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

Langkah selanjutnya

Last modified on May 26, 2026