Langsung ke konten utama

Apa itu upgrade atau downgrade langganan?

Mengubah rencana memungkinkan Anda memindahkan pelanggan antara tingkat atau kuantitas langganan. Gunakan ini untuk:
  • Menyesuaikan harga dengan penggunaan atau fitur
  • Beralih dari bulanan ke tahunan (atau sebaliknya)
  • Menyesuaikan kuantitas untuk produk berbasis kursi
Perubahan rencana dapat memicu biaya segera tergantung pada mode proration yang Anda pilih.

Kapan menggunakan perubahan rencana

  • Upgrade ketika pelanggan membutuhkan lebih banyak fitur, penggunaan, atau kursi
  • Downgrade ketika penggunaan menurun
  • Memigrasi pengguna ke produk atau harga baru tanpa membatalkan langganan mereka

Prasyarat

Sebelum menerapkan perubahan rencana langganan, pastikan Anda memiliki:
  • Akun pedagang Dodo Payments dengan produk langganan aktif
  • Kredensial API (kunci API dan kunci rahasia webhook) dari dasbor
  • Langganan aktif yang ada untuk dimodifikasi
  • Titik akhir webhook yang dikonfigurasi untuk menangani peristiwa langganan
Untuk instruksi pengaturan yang lebih rinci, lihat Panduan Integrasi.

Panduan Implementasi Langkah-demi-Langkah

Ikuti panduan komprehensif ini untuk menerapkan perubahan rencana langganan di aplikasi Anda:
1

Pahami Persyaratan Perubahan Rencana

Sebelum menerapkan, tentukan:
  • Produk langganan mana yang dapat diubah ke yang lain
  • Mode proration mana yang sesuai dengan model bisnis Anda
  • Cara menangani perubahan rencana yang gagal dengan baik
  • Peristiwa webhook mana yang harus dilacak untuk manajemen status
Uji perubahan rencana secara menyeluruh dalam mode uji sebelum menerapkannya di produksi.
2

Pilih Strategi Proration Anda

Pilih pendekatan penagihan yang sesuai dengan kebutuhan bisnis Anda:
Terbaik untuk: aplikasi SaaS yang ingin mengenakan biaya secara adil untuk waktu yang tidak terpakai
  • Menghitung jumlah prorata yang tepat berdasarkan waktu siklus yang tersisa
  • Mengenakan biaya jumlah prorata berdasarkan waktu yang tidak terpakai yang tersisa dalam siklus
  • Memberikan penagihan yang transparan kepada pelanggan
3

Terapkan API Ubah Rencana

Gunakan API Ubah Rencana untuk memodifikasi detail langganan:
subscription_id
string
required
ID langganan aktif yang akan dimodifikasi.
product_id
string
required
ID produk baru untuk mengubah langganan.
quantity
integer
default:"1"
Jumlah unit untuk rencana baru (untuk produk berbasis kursi).
proration_billing_mode
string
required
Cara menangani penagihan segera: prorated_immediately, full_immediately, atau difference_immediately.
addons
array
Addon opsional untuk rencana baru. Meninggalkan ini kosong akan menghapus addon yang ada.
4

Tangani Peristiwa Webhook

Siapkan penanganan webhook untuk melacak hasil perubahan rencana:
  • subscription.active: Perubahan rencana berhasil, langganan diperbarui
  • subscription.plan_changed: Rencana langganan diubah (upgrade/downgrade/pembaruan addon)
  • subscription.on_hold: Biaya perubahan rencana gagal, langganan ditangguhkan
  • payment.succeeded: Biaya segera untuk perubahan rencana berhasil
  • payment.failed: Biaya segera gagal
Selalu verifikasi tanda tangan webhook dan terapkan pemrosesan peristiwa idempotent.
5

Perbarui Status Aplikasi Anda

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

Uji dan Pantau

Uji implementasi Anda secara menyeluruh:
  • Uji semua mode proration dengan berbagai skenario
  • Verifikasi penanganan webhook berfungsi dengan benar
  • Pantau tingkat keberhasilan perubahan rencana
  • Siapkan peringatan untuk perubahan rencana yang gagal
Implementasi perubahan rencana langganan Anda sekarang siap untuk digunakan di produksi.

Pratinjau Perubahan Rencana

Sebelum berkomitmen pada perubahan rencana, gunakan API Pratinjau untuk menunjukkan kepada pelanggan persis berapa biaya 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 membangun dialog konfirmasi yang menunjukkan kepada pelanggan jumlah pasti yang akan mereka bayar sebelum mereka mengonfirmasi perubahan rencana.

API Ubah Rencana

Gunakan API Ubah Rencana untuk memodifikasi produk, kuantitas, dan perilaku proration untuk langganan aktif.

Contoh mulai cepat

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"
}
Bidang seperti invoice_id dan payment_id hanya dikembalikan ketika biaya segera dan/atau faktur dibuat selama perubahan rencana. Selalu bergantung pada peristiwa webhook (misalnya, payment.succeeded, subscription.plan_changed) untuk mengonfirmasi hasil.
Jika biaya segera gagal, langganan mungkin berpindah ke subscription.on_hold hingga pembayaran berhasil.

Mengelola Addons

Saat mengubah rencana langganan, Anda juga dapat memodifikasi addons:
// 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
});
Addons termasuk dalam perhitungan proration dan akan dikenakan biaya sesuai dengan mode proration yang dipilih.

Mode Proration

Pilih cara menagih pelanggan saat mengubah rencana:

prorated_immediately

  • Mengenakan biaya untuk selisih parsial dalam siklus saat ini
  • Jika dalam masa percobaan, mengenakan biaya segera dan beralih ke rencana baru sekarang
  • Downgrade: dapat menghasilkan kredit prorata yang diterapkan pada pembaruan di masa mendatang

full_immediately

  • Mengenakan biaya penuh untuk rencana baru segera
  • Mengabaikan waktu yang tersisa dari rencana lama
Kredit yang dibuat oleh downgrade menggunakan difference_immediately bersifat spesifik langganan dan berbeda dari Kredit Pelanggan. Mereka secara otomatis diterapkan pada pembaruan di masa mendatang dari langganan yang sama dan tidak dapat dipindahkan antar langganan.

difference_immediately

  • Upgrade: segera kenakan biaya selisih harga antara rencana lama dan baru
  • Downgrade: tambahkan nilai yang tersisa sebagai kredit internal ke langganan dan terapkan secara otomatis pada pembaruan

Skenario Contoh

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
Pilih prorated_immediately untuk akuntansi waktu yang adil; pilih full_immediately untuk memulai ulang penagihan; gunakan difference_immediately untuk upgrade sederhana dan kredit otomatis pada downgrade.

Menangani webhook

Lacak status langganan melalui webhook untuk mengonfirmasi perubahan rencana dan pembayaran.

Jenis peristiwa yang harus ditangani

  • subscription.active: langganan diaktifkan
  • subscription.plan_changed: rencana langganan diubah (upgrade/downgrade/perubahan addon)
  • subscription.on_hold: biaya gagal, langganan ditangguhkan
  • subscription.renewed: pembaruan berhasil
  • payment.succeeded: pembayaran untuk perubahan rencana atau pembaruan berhasil
  • payment.failed: pembayaran gagal
Kami merekomendasikan untuk menggerakkan logika bisnis dari peristiwa langganan dan menggunakan peristiwa pembayaran untuk konfirmasi dan rekonsiliasi.

Verifikasi tanda tangan dan tangani 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 yang lebih rinci, lihat Payload webhook langganan dan Payload webhook pembayaran.

Praktik Terbaik

Ikuti rekomendasi ini untuk perubahan rencana langganan yang andal:

Strategi Perubahan Rencana

  • Uji secara menyeluruh: Selalu uji perubahan rencana dalam mode uji sebelum produksi
  • Pilih proration dengan hati-hati: Pilih mode proration yang sesuai dengan model bisnis Anda
  • Tangani kegagalan dengan baik: Terapkan penanganan kesalahan yang tepat dan logika pengulangan
  • Pantau tingkat keberhasilan: Lacak tingkat keberhasilan/kegagalan perubahan rencana dan selidiki masalah

Implementasi Webhook

  • Verifikasi tanda tangan: Selalu validasi tanda tangan webhook untuk memastikan keaslian
  • Terapkan idempotensi: Tangani peristiwa webhook duplikat dengan baik
  • Proses secara asinkron: Jangan memblokir respons webhook dengan operasi berat
  • Catat semuanya: Pertahankan log yang rinci untuk tujuan debugging dan audit

Pengalaman Pengguna

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

Masalah Umum dan Solusi

Atasi masalah umum yang dihadapi selama perubahan rencana langganan:
Gejala: Panggilan API berhasil tetapi langganan tetap pada rencana lamaPenyebab umum:
  • Pemrosesan webhook gagal atau tertunda
  • Status aplikasi tidak diperbarui setelah menerima webhook
  • Masalah transaksi basis data selama pembaruan status
Solusi:
  • Terapkan penanganan webhook yang kuat dengan logika pengulangan
  • Gunakan operasi idempotent untuk pembaruan status
  • Tambahkan pemantauan untuk mendeteksi dan memberi tahu tentang peristiwa webhook yang terlewat
  • Verifikasi titik akhir webhook dapat diakses dan merespons dengan benar
Gejala: Pelanggan melakukan downgrade tetapi tidak melihat saldo kreditPenyebab umum:
  • Harapan mode proration: downgrade mengkredit selisih harga penuh rencana dengan difference_immediately, sementara prorated_immediately membuat kredit prorata berdasarkan waktu yang tersisa dalam siklus
  • Kredit bersifat spesifik langganan dan tidak dapat dipindahkan antar langganan
  • Saldo kredit tidak terlihat di dasbor pelanggan
Solusi:
  • Gunakan difference_immediately untuk downgrade ketika Anda ingin kredit otomatis
  • Jelaskan kepada pelanggan bahwa kredit diterapkan pada pembaruan di masa mendatang dari langganan yang sama
  • Terapkan portal pelanggan untuk menunjukkan saldo kredit
  • Periksa pratinjau faktur berikutnya untuk melihat kredit yang diterapkan
Gejala: Peristiwa webhook ditolak karena tanda tangan tidak validPenyebab umum:
  • Kunci rahasia webhook yang salah
  • Badan permintaan mentah dimodifikasi sebelum verifikasi tanda tangan
  • Algoritma verifikasi tanda tangan yang salah
Solusi:
  • Verifikasi Anda menggunakan DODO_WEBHOOK_SECRET yang benar dari dasbor
  • Baca badan permintaan mentah sebelum middleware parsing JSON apa pun
  • Gunakan pustaka verifikasi webhook standar untuk platform Anda
  • Uji verifikasi tanda tangan webhook di lingkungan pengembangan
Gejala: API mengembalikan kesalahan 422 Unprocessable EntityPenyebab umum:
  • ID langganan atau ID produk tidak valid
  • Langganan tidak dalam status aktif
  • Parameter yang diperlukan hilang
  • Produk tidak tersedia untuk perubahan rencana
Solusi:
  • Verifikasi langganan ada dan aktif
  • Periksa ID produk valid dan tersedia
  • Pastikan semua parameter yang diperlukan disediakan
  • Tinjau dokumentasi API untuk persyaratan parameter
Gejala: Perubahan rencana dimulai tetapi biaya segera gagalPenyebab umum:
  • Dana tidak mencukupi pada metode pembayaran pelanggan
  • Metode pembayaran kedaluwarsa atau tidak valid
  • Bank menolak transaksi
  • Deteksi penipuan memblokir biaya
Solusi:
  • Tangani peristiwa webhook payment.failed dengan tepat
  • Beri tahu pelanggan untuk memperbarui metode pembayaran
  • Terapkan logika pengulangan untuk kegagalan sementara
  • Pertimbangkan untuk mengizinkan perubahan rencana dengan biaya segera yang gagal
Gejala: Biaya perubahan rencana gagal dan langganan berpindah ke status on_holdApa yang terjadi: Ketika biaya perubahan rencana gagal, langganan secara otomatis ditempatkan dalam status on_hold. Langganan tidak akan diperbarui secara otomatis hingga metode pembayaran diperbarui.Solusi: Perbarui metode pembayaran untuk mengaktifkan kembali langgananUntuk mengaktifkan kembali langganan dari status on_hold setelah perubahan rencana yang gagal:
  1. Perbarui metode pembayaran menggunakan API Perbarui Metode Pembayaran
  2. Pembuatan biaya otomatis: API secara otomatis membuat biaya untuk tunggakan yang tersisa
  3. Pembuatan faktur: Faktur dibuat untuk biaya tersebut
  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;
}
Peristiwa webhook yang harus dipantau:
  • subscription.on_hold: Langganan ditempatkan pada hold (diperoleh ketika biaya perubahan rencana gagal)
  • payment.succeeded: Pembayaran untuk tunggakan yang tersisa berhasil (setelah memperbarui metode pembayaran)
  • subscription.active: Langganan diaktifkan kembali setelah pembayaran berhasil
Praktik terbaik:
  • Segera beri tahu pelanggan ketika biaya perubahan rencana gagal
  • Berikan instruksi yang jelas tentang cara memperbarui metode pembayaran mereka
  • Pantau peristiwa webhook untuk melacak status reaktivasi
  • Pertimbangkan untuk menerapkan logika pengulangan otomatis untuk kegagalan pembayaran sementara

Referensi API Perbarui Metode Pembayaran

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

Menguji Implementasi Anda

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

Siapkan lingkungan uji

  • Gunakan kunci API uji dan produk uji
  • Buat langganan uji dengan berbagai jenis rencana
  • Konfigurasi titik akhir webhook uji
  • Siapkan pemantauan dan pencatatan
2

Uji berbagai mode proration

  • Uji prorated_immediately dengan berbagai posisi siklus penagihan
  • Uji difference_immediately untuk upgrade dan downgrade
  • Uji full_immediately untuk mengatur ulang siklus penagihan
  • Verifikasi perhitungan kredit sudah benar
3

Uji penanganan webhook

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

Uji skenario kesalahan

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

Pantau di produksi

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

Penanganan Kesalahan

Tangani kesalahan API umum dengan baik dalam implementasi Anda:

Kode Status HTTP

Permintaan perubahan rencana diproses dengan sukses. Langganan sedang diperbarui dan pemrosesan pembayaran telah dimulai.
Parameter permintaan tidak valid. Periksa bahwa semua bidang yang diperlukan disediakan dan diformat dengan benar.
Kunci API 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.).
Terjadi kesalahan server. Coba ulang permintaan setelah jeda singkat.

Format Respons Kesalahan

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

Langkah Selanjutnya