메인 콘텐츠로 건너뛰기

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
필수
The ID of the active subscription to modify.
product_id
string
필수
The new product ID to change the subscription to.
quantity
integer
기본값:"1"
Number of units for the new plan (for seat-based products).
proration_billing_mode
string
필수
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_code
string
새로운 플랜에 적용할 선택적 할인 코드입니다. 제공된 경우, 할인 코드를 유효성 검증하고 플랜 변경에 적용합니다. 제공되지 않은 경우, 구독에 기존 할인 코드가 preserve_on_plan_change=true와 함께 있으면 (새 제품에 적용 가능한 경우) 기존 할인이 유지됩니다.
effective_at
string
기본값:"immediately"
플랜 변경 적용 시기:
  • immediately (기본값): 즉시 플랜 변경 적용
  • next_billing_date: 다음 청구 날짜에 변경 예약. 고객은 청구 기간이 끝날 때까지 현재 플랜을 유지합니다.
next_billing_date를 다운그레이드에 사용하여 고객이 청구 기간이 끝날 때까지 현재 플랜 혜택을 유지할 수 있도록 합니다.
4

Handle Webhook Events

플랜 변경 결과를 추적하기 위한 웹훅 처리 설정:
  • subscription.active: 플랜 변경 성공, 구독 업데이트됨
  • subscription.plan_changed: 구독 플랜 변경 (업그레이드/다운그레이드/애드온 업데이트)
  • subscription.on_hold: 플랜 변경 요금 실패, 구독 일시 중지됨
  • payment.succeeded: 플랜 변경 즉시 요금 성공
  • payment.failed: 즉시 요금 실패
항상 웹훅 서명을 검증하고 멱등한 이벤트 처리를 구현하십시오.
5

Update Your Application State

웹훅 이벤트에 따라 애플리케이션 업데이트:
  • 신규 플랜에 따라 기능 부여/회수
  • 고객 대시보드에 신규 플랜 세부사항 업데이트
  • 플랜 변경에 관한 확인 이메일 발송
  • 감사 목적으로 청구 변경 사항 기록
6

Test and Monitor

구현을 철저히 테스트하십시오:
  • 다양한 시나리오로 모든 비례 요금 모드를 테스트
  • 웹훅 처리가 제대로 작동하는지 확인
  • 플랜 변경 성공률 모니터링
  • 실패한 플랜 변경에 대한 알림 설정
구독 플랜 변경 구현이 이제 프로덕션용으로 준비되었습니다.

플랜 변경 미리보기

플랜 변경을 확정하기 전에, 고객에게 정확히 청구될 금액을 보여주기 위해 Preview API를 사용하십시오.
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);
프리뷰 API를 사용하여 플랜 변경을 확인하기 전에 고객에게 정확히 청구될 금액을 표시하는 확인 대화상자를 구축하십시오.

플랜 변경 API

플랜 변경 API를 사용하여 활성 구독의 제품, 수량, 비례 요금 동작을 수정합니다.

빠른 시작 예제

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"
}
invoice_idpayment_id와 같은 필드는 플랜 변경 중에 즉시 요금 청구 및/또는 송장이 생성될 때만 반환됩니다. 항상 웹훅 이벤트 (payment.succeeded, subscription.plan_changed 등)를 통해 결과를 확인하십시오.
즉시 요금 청구에 실패하면, 구독은 subscription.on_hold로 전환될 수 있습니다. 결제가 성공할 때까지.

애드온 관리

구독 플랜을 변경할 때 애드온도 수정할 수 있습니다:
// 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
});
애드온은 비례 요금 계산에 포함되며 선택한 비례 요금 모드에 따라 요금이 청구됩니다.

할인 코드 적용

구독 플랜 변경 시 할인 코드를 적용할 수 있습니다. 이는 업그레이드 또는 마이그레이션에 대한 프로모션 가격을 제공하는 데 유용합니다.
// Apply a discount code during plan change
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_pro',
  quantity: 1,
  proration_billing_mode: 'prorated_immediately',
  discount_code: 'UPGRADE20'
});

플랜 변경 시 할인 동작

시나리오동작
discount_code 제공됨새로운 플랜에 할인을 적용합니다.
코드가 제공되지 않았으나 preserve_on_plan_change=true와 함께 기존 할인 있음새로운 제품에 적용 가능한 경우, 기존 할인이 자동으로 유지됩니다.
코드가 제공되지 않고, 유지 가능한 할인 없음새로운 플랜에는 할인이 적용되지 않습니다.
플랜 변경 미리보기 APIdiscount_code와 함께 사용하여 고객에게 플랜 변경 확인 전에 얼마나 절약할 수 있는지 정확히 보여줍니다.

비례 요금 모드

플랜 변경 시 고객에게 청구할 방식을 선택하십시오:

prorated_immediately

  • 현재 사이클에서 부분 차이에 대한 요금을 청구합니다
  • 체험 중이라면 즉시 요금을 부과하고 새 플랜으로 전환합니다
  • 다운그레이드: 일부 환불을 후속 갱신에 적용할 수 있는 경우 생성됩니다

full_immediately

  • 새 플랜의 전체 금액을 즉시 청구합니다
  • 오래된 플랜의 남은 시간을 무시합니다
difference_immediately를 사용하여 다운그레이드할 때 생성된 크레딧은 구독에 범위가 지정되며, 크레딧 기반 청구 권리와는 다릅니다. 이 크레딧은 동일한 구독의 후속 갱신에 자동으로 적용되며, 구독 간에 이전되지 않습니다.

difference_immediately

  • 업그레이드: 오래된 플랜과 새로운 플랜 간의 가격 차이를 즉시 청구합니다
  • 다운그레이드: 남은 가치를 내부 크레딧으로 추가하고 자동 갱신 시 적용합니다

do_not_bill

  • 요금이나 크레딧이 계산되지 않습니다
  • 고객은 즉시 변경된 플랜으로 전환되며 청구 조정이 없습니다
  • 청구 주기는 변하지 않습니다
  • 주로 무료 마이그레이션, 무료 플랜 전환, 비용 차이 흡수를 위한 것입니다
기능prorated_immediatelydifference_immediatelyfull_immediatelydo_not_bill
업그레이드 요금남은 일수에 대한 비례 차이플랜 간의 전체 가격 차이새 플랜의 전체 금액요금 없음
다운그레이드 크레딧남은 일수에 대한 비례 크레딧전체 가격 차이를 크레딧으로크레딧 없음크레딧 없음
청구 주기변하지 않음변하지 않음오늘로 초기화변하지 않음
체험 동작체험 종료, 즉시 요금 부과체험 종료, 즉시 요금 부과체험 종료, 전체 금액 부과체험 종료, 요금 없음
최적사용공정한 시간 기반 청구간단한 업그레이드/다운그레이드 계산청구 주기 초기화무료 마이그레이션 또는 무료 전환
복잡도중간 (일 계산)낮음 (간단한 뺄셈)낮음 (전체 청구)없음

예제 시나리오

다음 기준 숫자를 일관되게 사용하십시오:
  • 현재 플랜: Basic $30/월
  • 업그레이드 목표: Pro $80/월
  • 다운그레이드 목표 (Pro에서): Starter $20/월
  • 청구 주기: 30일, 1월 1일에 시작
  • 플랜 변경 시점: 1월 16일 (남은 15일, 사용한 15일)
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 }
  ]
})

각 모드가 청구를 처리하는 방식

공정한 시간 기반을 위해서는 prorated_immediately를 선택하십시오; 청구를 재시작하려면 full_immediately를 선택하십시오; 간단한 업그레이드와 다운그레이드 시 자동 크레딧을 위해서는 difference_immediately를 사용하십시오; 또는 어떤 청구 조정 없이 플랜을 변경하려면 do_not_bill를 사용하십시오.

결제 실패 처리

플랜 변경 결제가 실패했을 때의 처리를 on_payment_failure 매개변수를 사용하여 제어하십시오.

결제 실패 모드

지정하지 않은 경우, on_payment_failure 매개변수는 대시보드에 구성된 비즈니스 수준의 기본 설정을 사용합니다.

각 모드의 사용 시기

시나리오권장 모드이유
프리미엄 기능으로의 업그레이드prevent_change접근권 부여 전에 결제 보장
수량 증가 (더 많은 좌석)prevent_change결제 없이 사용 방지
플랜 다운그레이드apply_change고객이 지출을 줄임
신뢰할 수 있는 기업 고객apply_change비결제에 대한 위험이 낮음
체험에서 유료 전환prevent_change중요한 결제 순간

웹훅 처리

웹훅을 통해 구독 상태를 추적하여 플랜 변경 및 결제를 확인합니다.

처리해야 할 이벤트 유형

  • subscription.active: 구독 활성화됨
  • subscription.plan_changed: 구독 플랜 변경 (업그레이드/다운그레이드/애드온 변경)
  • subscription.on_hold: 요금 실패, 구독 일시 중지
  • subscription.renewed: 갱신 성공
  • payment.succeeded: 플랜 변경 또는 갱신에 대한 결제 성공
  • payment.failed: 결제 실패
구독 이벤트에서 비즈니스 로직을 운전하고 결제 이벤트를 확인 및 조정에 사용하길 권장합니다.

서명 확인 및 의도 처리

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 });
}
상세한 페이로드 스키마는 구독 웹훅 페이로드결제 웹훅 페이로드를 참조하십시오.

모범 사례

안정적인 구독 플랜 변경을 위해 다음 권장 사항을 따르십시오:

플랜 변경 전략

  • 철저하게 테스트: 프로덕션 전에 항상 테스트 모드에서 플랜 변경을 테스트하세요
  • 비례 요금 신중히 선택: 비즈니스 모델에 맞는 비례 요금 모드를 선택하세요
  • 실패를 우아하게 처리: 적절한 오류 처리 및 재시도 로직 구현
  • 성공률 모니터링: 플랜 변경 성공/실패율을 추적하고 문제를 조사하세요

웹훅 구현

  • 서명 확인: 항상 웹훅 서명을 검증하여 진위성을 확인하세요
  • 멱등성 구현: 중복된 웹훅 이벤트를 우아하게 처리하세요
  • 비동기 처리: 무거운 작업으로 웹훅 응답을 차단하지 마세요
  • 모든 것 기록: 디버깅 및 감사 목적으로 세부 로그 유지하세요

사용자 경험

  • 명확한 소통: 고객에게 청구 변경 및 시기에 대해 알립니다
  • 확인 제공: 성공적인 플랜 변경에 대한 이메일 확인 발송
  • 경계 사례 처리: 체험 기간, 비례 요금 및 결제 실패를 고려하세요
  • UI 즉시 업데이트: 애플리케이션 인터페이스에서 플랜 변경 반영하세요

일반적인 문제와 해결책

구독 플랜 변경 중에 발생하는 일반적인 문제를 해결하세요:
증상: API 호출 성공했으나 구독이 이전 플랜에 남아 있음일반적인 원인:
  • 웹훅 처리가 실패했거나 지연됨
  • 웹훅 수신 후 애플리케이션 상태가 업데이트되지 않음
  • 상태 업데이트 중 데이터베이스 트랜잭션 문제
해결책:
  • 견고한 웹훅 처리 및 재시도 로직 구현
  • 상태 업데이트에 대한 멱등한 작업 사용
  • 놓친 웹훅 이벤트를 감지하고 알림
  • 웹훅 엔드포인트가 접근 가능하며 올바르게 응답하는지 확인
증상: 고객이 다운그레이드했으나 크레딧 잔액을 보지 못함일반적인 원인:
  • 비례 요금 모드 기대: 다운그레이드는 difference_immediately로 전체 플랜 가격 차이를 크레딧으로 적용하고, prorated_immediately는 사이클에 남은 시간을 기반으로 비례 크레딧을 생성
  • 크레딧은 구독에 국한되어 있으며 구독 간에 이전되지 않음
  • 고객 대시보드에 크레딧 잔액 표시되지 않음
해결책:
  • 자동 크레딧을 원할 때 다운그레이드에 difference_immediately 사용
  • 크레딧이 동일한 구독의 미래 갱신에 적용된다고 고객에게 설명
  • 크레딧 잔액을 보여주는 고객 포털 구현
  • 다음 청구서 미리보기를 확인하여 적용된 크레딧 확인
증상: 웹훅 이벤트가 잘못된 서명으로 인해 거부됨일반적인 원인:
  • 잘못된 웹훅 시크릿 키
  • JSON 파싱 미들웨어 전에 원시 요청 본문이 수정됨
  • 잘못된 서명 검증 알고리즘
해결책:
  • 대시보드에서 올바른 DODO_WEBHOOK_SECRET 사용을 확인
  • 어떤 JSON 파싱 미들웨어 이전에 원시 요청 본문 읽기
  • 플랫폼 표준 웹훅 검증 라이브러리 사용
  • 개발 환경에서 웹훅 서명 검증 테스트
증상: API가 422 Unprocessable Entity 오류 반환일반적인 원인:
  • 잘못된 구독 ID 또는 제품 ID
  • 구독이 활성 상태가 아님
  • 필요한 매개변수 누락
  • 플랜 변경에 사용할 수 없는 제품
해결책:
  • 구독이 존재하고 활성 상태인지 확인
  • 제품 ID가 유효하고 사용 가능한지 확인
  • 모든 필요한 매개변수가 제공되었는지 확인
  • 매개변수 요구 사항에 대한 API 문서 검토
증상: 플랜 변경이 시작됐으나 즉시 요금이 실패일반적인 원인:
  • 고객의 결제 수단에 자금이 부족함
  • 결제 수단이 만료되었거나 유효하지 않음
  • 은행이 거래를 거부함
  • 사기 탐지가 요금을 차단함
해결책:
  • payment.failed 웹훅 이벤트를 적절히 처리
  • 고객에게 결제 수단 업데이트 알림
  • 일시적 실패에 대한 재시도 로직 구현
  • 실패한 즉시 요금에도 플랜 변경 허용 고려
증상: 플랜 변경 요금 실패 후 구독이 on_hold 상태로 이동발생 상황: 플랜 변경 요금이 실패하면 구독이 자동으로 on_hold 상태로 전환됩니다. 결제 수단이 업데이트될 때까지 구독은 자동으로 갱신되지 않습니다.해결책: 결제 수단을 업데이트하여 구독을 재활성화플랜 변경 실패 후 on_hold 상태에서 구독을 다시 활성화하려면:
  1. 결제 수단 업데이트 Update Payment Method API 사용
  2. 자동 요금 생성: API가 자동으로 남은 금액에 대해 요금을 생성
  3. 청구서 생성: 요금에 대한 송장 생성
  4. 결제 처리: 새로운 결제 수단으로 결제를 처리
  5. 재활성화: 결제가 성공하면 구독이 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;
}
모니터링할 웹훅 이벤트:
  • subscription.on_hold: 구독 일시 정지 (플랜 변경 요금 실패 시 수신)
  • payment.succeeded: 남은 금액에 대한 결제가 성공 (결제 수단 업데이트 후)
  • subscription.active: 성공적인 결제 후 구독 재활성화
모범 사례:
  • 플랜 변경 요금이 실패할 때 즉시 고객에게 알림
  • 결제 수단을 업데이트하는 방법에 대한 명확한 지침 제공
  • 재활성화 상태를 추적하기 위해 웹훅 이벤트 모니터링
  • 일시적인 결제 실패에 대한 자동 재시도 로직 구현 고려

Update Payment Method API Reference

결제 수단 업데이트 및 구독 재활성화에 대한 전체 API 문서를 보십시오.

구현 테스트

구독 플랜 변경 구현을 철저히 테스트하려면 다음 단계를 따르십시오:
1

Set up test environment

  • 테스트 API 키 및 테스트 제품 사용
  • 다양한 플랜 유형의 테스트 구독 생성
  • 테스트 웹훅 엔드포인트 구성
  • 모니터링 및 로깅 설정
2

Test different proration modes

  • 다양한 청구 주기 위치에서 prorated_immediately 테스트
  • 업그레이드 및 다운그레이드에 difference_immediately 테스트
  • 청구 주기를 재설정하기 위해 full_immediately 테스트
  • 요금 없음/크레딧 없음 플랜 전환에 do_not_bill 테스트
  • 크레딧 계산이 정확한지 확인
3

Test webhook handling

  • 모든 관련 웹훅 이벤트 수신 확인
  • 웹훅 서명 확인 테스트
  • 중복된 웹훅 이벤트를 우아하게 처리
  • 웹훅 처리 실패 시나리오 테스트
4

Test error scenarios

  • 무효한 구독 ID로 테스트
  • 만료된 결제 수단으로 테스트
  • 네트워크 장애 및 타임아웃 테스트
  • 자금 부족으로 테스트
5

Monitor in production

  • 실패한 플랜 변경에 대한 알림 설정
  • 웹훅 처리 시간 모니터링
  • 플랜 변경 성공률 추적
  • 플랜 변경 문제에 대한 고객 지원 티켓 검토

오류 처리

구현에서 일반적인 API 오류를 우아하게 처리하세요:

HTTP 상태 코드

플랜 변경 요청이 성공적으로 처리되었습니다. 구독이 업데이트되고 결제 처리가 시작되었습니다.
잘못된 요청 매개변수. 모든 필요한 필드가 올바르게 제공되고 형식이 지정되었는지 확인하세요.
잘못되었거나 누락된 API 키. DODO_PAYMENTS_API_KEY가 올바르고 적절한 권한이 있는지 확인하세요.
구독 ID를 찾을 수 없거나 계정에 속하지 않습니다.
구독을 변경할 수 없음 (예: 이미 취소됨, 사용할 수 없음 등).
서버 오류 발생. 잠시 후 요청을 다시 시도하십시오.

오류 응답 형식

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

다음 단계

Last modified on April 20, 2026