요금제 변경 미리보기
구독 요금제 변경의 영향을 실제로 변경하기 전에 미리 확인합니다. 즉각적인 청구 금액과 새로운 구독 세부정보를 반환하지만 실제 변경은 하지 않습니다.
import DodoPayments from 'dodopayments';
const client = new DodoPayments({
bearerToken: process.env['DODO_PAYMENTS_API_KEY'], // This is the default and can be omitted
});
const response = await client.subscriptions.previewChangePlan('sub_Iuaq622bbmmfOGrVTqdXv', {
product_id: 'product_id',
proration_billing_mode: 'prorated_immediately',
quantity: 0,
});
console.log(response.immediate_charge);import os
from dodopayments import DodoPayments
client = DodoPayments(
bearer_token=os.environ.get("DODO_PAYMENTS_API_KEY"), # This is the default and can be omitted
)
response = client.subscriptions.preview_change_plan(
subscription_id="sub_Iuaq622bbmmfOGrVTqdXv",
product_id="product_id",
proration_billing_mode="prorated_immediately",
quantity=0,
)
print(response.immediate_charge)package main
import (
"context"
"fmt"
"github.com/dodopayments/dodopayments-go"
"github.com/dodopayments/dodopayments-go/option"
)
func main() {
client := dodopayments.NewClient(
option.WithBearerToken("My Bearer Token"),
)
response, err := client.Subscriptions.PreviewChangePlan(
context.TODO(),
"sub_Iuaq622bbmmfOGrVTqdXv",
dodopayments.SubscriptionPreviewChangePlanParams{
UpdateSubscriptionPlanReq: dodopayments.UpdateSubscriptionPlanReqParam{
ProductID: dodopayments.F("product_id"),
ProrationBillingMode: dodopayments.F(dodopayments.UpdateSubscriptionPlanReqProrationBillingModeProratedImmediately),
Quantity: dodopayments.F(int64(0)),
},
},
)
if err != nil {
panic(err.Error())
}
fmt.Printf("%+v\n", response.ImmediateCharge)
}
package com.dodopayments.api.example;
import com.dodopayments.api.client.DodoPaymentsClient;
import com.dodopayments.api.client.okhttp.DodoPaymentsOkHttpClient;
import com.dodopayments.api.models.subscriptions.SubscriptionPreviewChangePlanParams;
import com.dodopayments.api.models.subscriptions.SubscriptionPreviewChangePlanResponse;
import com.dodopayments.api.models.subscriptions.UpdateSubscriptionPlanReq;
public final class Main {
private Main() {}
public static void main(String[] args) {
DodoPaymentsClient client = DodoPaymentsOkHttpClient.fromEnv();
SubscriptionPreviewChangePlanParams params = SubscriptionPreviewChangePlanParams.builder()
.subscriptionId("sub_Iuaq622bbmmfOGrVTqdXv")
.updateSubscriptionPlanReq(UpdateSubscriptionPlanReq.builder()
.productId("product_id")
.prorationBillingMode(UpdateSubscriptionPlanReq.ProrationBillingMode.PRORATED_IMMEDIATELY)
.quantity(0)
.build())
.build();
SubscriptionPreviewChangePlanResponse response = client.subscriptions().previewChangePlan(params);
}
}package com.dodopayments.api.example
import com.dodopayments.api.client.DodoPaymentsClient
import com.dodopayments.api.client.okhttp.DodoPaymentsOkHttpClient
import com.dodopayments.api.models.subscriptions.SubscriptionPreviewChangePlanParams
import com.dodopayments.api.models.subscriptions.SubscriptionPreviewChangePlanResponse
import com.dodopayments.api.models.subscriptions.UpdateSubscriptionPlanReq
fun main() {
val client: DodoPaymentsClient = DodoPaymentsOkHttpClient.fromEnv()
val params: SubscriptionPreviewChangePlanParams = SubscriptionPreviewChangePlanParams.builder()
.subscriptionId("sub_Iuaq622bbmmfOGrVTqdXv")
.updateSubscriptionPlanReq(UpdateSubscriptionPlanReq.builder()
.productId("product_id")
.prorationBillingMode(UpdateSubscriptionPlanReq.ProrationBillingMode.PRORATED_IMMEDIATELY)
.quantity(0)
.build())
.build()
val response: SubscriptionPreviewChangePlanResponse = client.subscriptions().previewChangePlan(params)
}require "dodopayments"
dodo_payments = Dodopayments::Client.new(
bearer_token: "My Bearer Token",
environment: "test_mode" # defaults to "live_mode"
)
response = dodo_payments.subscriptions.preview_change_plan(
"sub_Iuaq622bbmmfOGrVTqdXv",
product_id: "product_id",
proration_billing_mode: :prorated_immediately,
quantity: 0
)
puts(response)<?php
require_once dirname(__DIR__) . '/vendor/autoload.php';
use Dodopayments\Client;
use Dodopayments\Core\Exceptions\APIException;
$client = new Client(
bearerToken: getenv('DODO_PAYMENTS_API_KEY') ?: 'My Bearer Token',
environment: 'test_mode',
);
try {
$response = $client->subscriptions->previewChangePlan(
'sub_Iuaq622bbmmfOGrVTqdXv',
productID: 'product_id',
prorationBillingMode: 'prorated_immediately',
quantity: 0,
adaptiveCurrencyFeesInclusive: true,
addons: [['addonID' => 'addon_id', 'quantity' => 0]],
discountCode: 'discount_code',
discountCodes: ['string'],
effectiveAt: 'immediately',
metadata: ['foo' => 'string'],
onPaymentFailure: 'prevent_change',
);
var_dump($response);
} catch (APIException $e) {
echo $e->getMessage();
}using System;
using DodoPayments.Client;
using DodoPayments.Client.Models.Subscriptions;
DodoPaymentsClient client = new();
SubscriptionPreviewChangePlanParams parameters = new()
{
SubscriptionID = "sub_Iuaq622bbmmfOGrVTqdXv",
ProductID = "product_id",
ProrationBillingMode = SubscriptionPreviewChangePlanParamsProrationBillingMode.ProratedImmediately,
Quantity = 0,
};
var response = await client.Subscriptions.PreviewChangePlan(parameters);
Console.WriteLine(response);use dodopayments::Client;
#[tokio::main]
async fn main() -> dodopayments::Result<()> {
let client = Client::from_env()?;
let subscription_id = "subscription_id";
let result = client
.subscriptions()
.preview_change_plan()
.subscription_id(subscription_id)
.body(dodopayments::models::SubscriptionsChangePlanParams {
product_id: Some("product_id".to_string()),
proration_billing_mode: Some("prorated_immediately".to_string()),
quantity: Some(0),
..Default::default()
})
.await?;
println!("{result:?}");
Ok(())
}curl --request POST \
--url https://test.dodopayments.com/subscriptions/{subscription_id}/change-plan/preview \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"product_id": "<string>",
"quantity": 1,
"adaptive_currency_fees_inclusive": true,
"addons": [
{
"addon_id": "<string>",
"quantity": 1
}
],
"discount_code": "<string>",
"discount_codes": [
"<string>"
],
"metadata": {}
}
'{
"immediate_charge": {
"effective_at": "2023-11-07T05:31:56Z",
"line_items": [
{
"id": "<string>",
"product_id": "<string>",
"proration_factor": 123,
"quantity": 123,
"tax_inclusive": true,
"type": "subscription",
"unit_price": 123,
"description": "<string>",
"name": "<string>",
"tax": 123,
"tax_rate": 123
}
],
"summary": {
"customer_credits": 123,
"settlement_amount": 123,
"total_amount": 123,
"settlement_tax": 123,
"tax": 123
}
},
"new_plan": {
"addons": [
{
"addon_id": "<string>",
"quantity": 123
}
],
"billing": {
"city": "<string>",
"state": "<string>",
"street": "<string>",
"zipcode": "<string>"
},
"brand_id": "<string>",
"cancel_at_next_billing_date": true,
"created_at": "2023-11-07T05:31:56Z",
"credit_entitlement_cart": [
{
"credit_entitlement_id": "<string>",
"credit_entitlement_name": "<string>",
"credits_amount": "<string>",
"overage_balance": "<string>",
"overage_enabled": true,
"product_id": "<string>",
"remaining_balance": "<string>",
"rollover_enabled": true,
"unit": "<string>",
"expires_after_days": 123,
"low_balance_threshold_percent": 123,
"max_rollover_count": 123,
"overage_limit": "<string>",
"rollover_percentage": 123,
"rollover_timeframe_count": 123
}
],
"customer": {
"customer_id": "<string>",
"email": "<string>",
"name": "<string>",
"metadata": {},
"phone_number": "<string>"
},
"metadata": {},
"meter_credit_entitlement_cart": [
{
"credit_entitlement_id": "<string>",
"meter_id": "<string>",
"meter_name": "<string>",
"meter_units_per_credit": "<string>",
"product_id": "<string>"
}
],
"meters": [
{
"free_threshold": 123,
"measurement_unit": "<string>",
"meter_id": "<string>",
"name": "<string>",
"description": "<string>",
"price_per_unit": "10.50"
}
],
"next_billing_date": "2023-11-07T05:31:56Z",
"on_demand": true,
"payment_frequency_count": 123,
"previous_billing_date": "2023-11-07T05:31:56Z",
"product_id": "<string>",
"quantity": 123,
"recurring_pre_tax_amount": 123,
"subscription_id": "<string>",
"subscription_period_count": 123,
"tax_inclusive": true,
"trial_period_days": 123,
"cancellation_comment": "<string>",
"cancelled_at": "2023-11-07T05:31:56Z",
"custom_field_responses": [
{
"key": "<string>",
"value": "<string>"
}
],
"customer_business_name": "<string>",
"discount_cycles_remaining": 123,
"discount_id": "<string>",
"discounts": [
{
"amount": 123,
"business_id": "<string>",
"code": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"discount_id": "<string>",
"metadata": {},
"position": 123,
"preserve_on_plan_change": true,
"restricted_to": [
"<string>"
],
"times_used": 123,
"type": "percentage",
"cycles_remaining": 123,
"expires_at": "2023-11-07T05:31:56Z",
"name": "<string>",
"subscription_cycles": 123,
"usage_limit": 123
}
],
"expires_at": "2023-11-07T05:31:56Z",
"payment_method_id": "<string>",
"scheduled_change": {
"addons": [
{
"addon_id": "<string>",
"name": "<string>",
"quantity": 123
}
],
"created_at": "2023-11-07T05:31:56Z",
"effective_at": "2023-11-07T05:31:56Z",
"id": "<string>",
"product_id": "<string>",
"quantity": 123,
"product_description": "<string>",
"product_name": "<string>"
},
"tax_id": "<string>"
}
}사용 사례
- 체크아웃 확인: 고객이 요금제를 변경하기 전에 할당된 요금을 표시합니다.
- 가격 계산기: 애플리케이션에서 업그레이드/다운그레이드 계산기를 구축합니다.
- 고객 셀프 서비스: 고객이 정확한 가격으로 요금제 옵션을 탐색할 수 있도록 합니다.
- 할인 검증: 할인 코드가 요금제 변경 가격에 미치는 영향을 미리 봅니다.
discount_code in the preview request to see how the discount affects the immediate charge and new plan pricing before committing to the change.
응답 필드
미리보기 응답에는 다음이 포함됩니다:| 필드 | 설명 |
|---|---|
immediate_charge | 즉시 생성될 요금으로, 품목 및 요약 포함 |
new_plan | 요금제 변경 후 어떻게 보일지를 보여주는 전체 구독 객체 |
immediate_charge.summary contains the total amount that would be charged. Use this to display pricing to your customers before they confirm the plan change.인증
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
경로 매개변수
Subscription Id
본문
Unique identifier of the product to subscribe to
Proration Billing Mode
prorated_immediately, full_immediately, difference_immediately, do_not_bill Number of units to subscribe for. Must be at least 1.
x >= 0Whether adaptive currency fees should be included in the price (true) or added on top (false). If not specified, uses the subscription's stored setting.
Addons for the new plan. Note : Leaving this empty would remove any existing addons
Show child attributes
Show child attributes
DEPRECATED: Use discount_codes instead. Cannot be used together with discount_codes.
Stacked discount codes to apply to the new plan. Max 20. Cannot be used together with discount_code. If provided, replaces any existing discount codes. Empty array removes all discounts. If not provided (None), existing discounts with preserve_on_plan_change=true are preserved.
When to apply the plan change.
immediately(default): Apply the plan change right awaynext_billing_date: Schedule the change for the next billing date
immediately, next_billing_date Metadata for the payment. If not passed, the metadata of the subscription will be taken
Show child attributes
Show child attributes
Controls behavior when the plan change payment fails.
prevent_change: Keep subscription on current plan until payment succeedsapply_change(default): Apply plan change immediately regardless of payment outcome
If not specified, uses the business-level default setting.
prevent_change, apply_change import DodoPayments from 'dodopayments';
const client = new DodoPayments({
bearerToken: process.env['DODO_PAYMENTS_API_KEY'], // This is the default and can be omitted
});
const response = await client.subscriptions.previewChangePlan('sub_Iuaq622bbmmfOGrVTqdXv', {
product_id: 'product_id',
proration_billing_mode: 'prorated_immediately',
quantity: 0,
});
console.log(response.immediate_charge);import os
from dodopayments import DodoPayments
client = DodoPayments(
bearer_token=os.environ.get("DODO_PAYMENTS_API_KEY"), # This is the default and can be omitted
)
response = client.subscriptions.preview_change_plan(
subscription_id="sub_Iuaq622bbmmfOGrVTqdXv",
product_id="product_id",
proration_billing_mode="prorated_immediately",
quantity=0,
)
print(response.immediate_charge)package main
import (
"context"
"fmt"
"github.com/dodopayments/dodopayments-go"
"github.com/dodopayments/dodopayments-go/option"
)
func main() {
client := dodopayments.NewClient(
option.WithBearerToken("My Bearer Token"),
)
response, err := client.Subscriptions.PreviewChangePlan(
context.TODO(),
"sub_Iuaq622bbmmfOGrVTqdXv",
dodopayments.SubscriptionPreviewChangePlanParams{
UpdateSubscriptionPlanReq: dodopayments.UpdateSubscriptionPlanReqParam{
ProductID: dodopayments.F("product_id"),
ProrationBillingMode: dodopayments.F(dodopayments.UpdateSubscriptionPlanReqProrationBillingModeProratedImmediately),
Quantity: dodopayments.F(int64(0)),
},
},
)
if err != nil {
panic(err.Error())
}
fmt.Printf("%+v\n", response.ImmediateCharge)
}
package com.dodopayments.api.example;
import com.dodopayments.api.client.DodoPaymentsClient;
import com.dodopayments.api.client.okhttp.DodoPaymentsOkHttpClient;
import com.dodopayments.api.models.subscriptions.SubscriptionPreviewChangePlanParams;
import com.dodopayments.api.models.subscriptions.SubscriptionPreviewChangePlanResponse;
import com.dodopayments.api.models.subscriptions.UpdateSubscriptionPlanReq;
public final class Main {
private Main() {}
public static void main(String[] args) {
DodoPaymentsClient client = DodoPaymentsOkHttpClient.fromEnv();
SubscriptionPreviewChangePlanParams params = SubscriptionPreviewChangePlanParams.builder()
.subscriptionId("sub_Iuaq622bbmmfOGrVTqdXv")
.updateSubscriptionPlanReq(UpdateSubscriptionPlanReq.builder()
.productId("product_id")
.prorationBillingMode(UpdateSubscriptionPlanReq.ProrationBillingMode.PRORATED_IMMEDIATELY)
.quantity(0)
.build())
.build();
SubscriptionPreviewChangePlanResponse response = client.subscriptions().previewChangePlan(params);
}
}package com.dodopayments.api.example
import com.dodopayments.api.client.DodoPaymentsClient
import com.dodopayments.api.client.okhttp.DodoPaymentsOkHttpClient
import com.dodopayments.api.models.subscriptions.SubscriptionPreviewChangePlanParams
import com.dodopayments.api.models.subscriptions.SubscriptionPreviewChangePlanResponse
import com.dodopayments.api.models.subscriptions.UpdateSubscriptionPlanReq
fun main() {
val client: DodoPaymentsClient = DodoPaymentsOkHttpClient.fromEnv()
val params: SubscriptionPreviewChangePlanParams = SubscriptionPreviewChangePlanParams.builder()
.subscriptionId("sub_Iuaq622bbmmfOGrVTqdXv")
.updateSubscriptionPlanReq(UpdateSubscriptionPlanReq.builder()
.productId("product_id")
.prorationBillingMode(UpdateSubscriptionPlanReq.ProrationBillingMode.PRORATED_IMMEDIATELY)
.quantity(0)
.build())
.build()
val response: SubscriptionPreviewChangePlanResponse = client.subscriptions().previewChangePlan(params)
}require "dodopayments"
dodo_payments = Dodopayments::Client.new(
bearer_token: "My Bearer Token",
environment: "test_mode" # defaults to "live_mode"
)
response = dodo_payments.subscriptions.preview_change_plan(
"sub_Iuaq622bbmmfOGrVTqdXv",
product_id: "product_id",
proration_billing_mode: :prorated_immediately,
quantity: 0
)
puts(response)<?php
require_once dirname(__DIR__) . '/vendor/autoload.php';
use Dodopayments\Client;
use Dodopayments\Core\Exceptions\APIException;
$client = new Client(
bearerToken: getenv('DODO_PAYMENTS_API_KEY') ?: 'My Bearer Token',
environment: 'test_mode',
);
try {
$response = $client->subscriptions->previewChangePlan(
'sub_Iuaq622bbmmfOGrVTqdXv',
productID: 'product_id',
prorationBillingMode: 'prorated_immediately',
quantity: 0,
adaptiveCurrencyFeesInclusive: true,
addons: [['addonID' => 'addon_id', 'quantity' => 0]],
discountCode: 'discount_code',
discountCodes: ['string'],
effectiveAt: 'immediately',
metadata: ['foo' => 'string'],
onPaymentFailure: 'prevent_change',
);
var_dump($response);
} catch (APIException $e) {
echo $e->getMessage();
}using System;
using DodoPayments.Client;
using DodoPayments.Client.Models.Subscriptions;
DodoPaymentsClient client = new();
SubscriptionPreviewChangePlanParams parameters = new()
{
SubscriptionID = "sub_Iuaq622bbmmfOGrVTqdXv",
ProductID = "product_id",
ProrationBillingMode = SubscriptionPreviewChangePlanParamsProrationBillingMode.ProratedImmediately,
Quantity = 0,
};
var response = await client.Subscriptions.PreviewChangePlan(parameters);
Console.WriteLine(response);use dodopayments::Client;
#[tokio::main]
async fn main() -> dodopayments::Result<()> {
let client = Client::from_env()?;
let subscription_id = "subscription_id";
let result = client
.subscriptions()
.preview_change_plan()
.subscription_id(subscription_id)
.body(dodopayments::models::SubscriptionsChangePlanParams {
product_id: Some("product_id".to_string()),
proration_billing_mode: Some("prorated_immediately".to_string()),
quantity: Some(0),
..Default::default()
})
.await?;
println!("{result:?}");
Ok(())
}curl --request POST \
--url https://test.dodopayments.com/subscriptions/{subscription_id}/change-plan/preview \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"product_id": "<string>",
"quantity": 1,
"adaptive_currency_fees_inclusive": true,
"addons": [
{
"addon_id": "<string>",
"quantity": 1
}
],
"discount_code": "<string>",
"discount_codes": [
"<string>"
],
"metadata": {}
}
'{
"immediate_charge": {
"effective_at": "2023-11-07T05:31:56Z",
"line_items": [
{
"id": "<string>",
"product_id": "<string>",
"proration_factor": 123,
"quantity": 123,
"tax_inclusive": true,
"type": "subscription",
"unit_price": 123,
"description": "<string>",
"name": "<string>",
"tax": 123,
"tax_rate": 123
}
],
"summary": {
"customer_credits": 123,
"settlement_amount": 123,
"total_amount": 123,
"settlement_tax": 123,
"tax": 123
}
},
"new_plan": {
"addons": [
{
"addon_id": "<string>",
"quantity": 123
}
],
"billing": {
"city": "<string>",
"state": "<string>",
"street": "<string>",
"zipcode": "<string>"
},
"brand_id": "<string>",
"cancel_at_next_billing_date": true,
"created_at": "2023-11-07T05:31:56Z",
"credit_entitlement_cart": [
{
"credit_entitlement_id": "<string>",
"credit_entitlement_name": "<string>",
"credits_amount": "<string>",
"overage_balance": "<string>",
"overage_enabled": true,
"product_id": "<string>",
"remaining_balance": "<string>",
"rollover_enabled": true,
"unit": "<string>",
"expires_after_days": 123,
"low_balance_threshold_percent": 123,
"max_rollover_count": 123,
"overage_limit": "<string>",
"rollover_percentage": 123,
"rollover_timeframe_count": 123
}
],
"customer": {
"customer_id": "<string>",
"email": "<string>",
"name": "<string>",
"metadata": {},
"phone_number": "<string>"
},
"metadata": {},
"meter_credit_entitlement_cart": [
{
"credit_entitlement_id": "<string>",
"meter_id": "<string>",
"meter_name": "<string>",
"meter_units_per_credit": "<string>",
"product_id": "<string>"
}
],
"meters": [
{
"free_threshold": 123,
"measurement_unit": "<string>",
"meter_id": "<string>",
"name": "<string>",
"description": "<string>",
"price_per_unit": "10.50"
}
],
"next_billing_date": "2023-11-07T05:31:56Z",
"on_demand": true,
"payment_frequency_count": 123,
"previous_billing_date": "2023-11-07T05:31:56Z",
"product_id": "<string>",
"quantity": 123,
"recurring_pre_tax_amount": 123,
"subscription_id": "<string>",
"subscription_period_count": 123,
"tax_inclusive": true,
"trial_period_days": 123,
"cancellation_comment": "<string>",
"cancelled_at": "2023-11-07T05:31:56Z",
"custom_field_responses": [
{
"key": "<string>",
"value": "<string>"
}
],
"customer_business_name": "<string>",
"discount_cycles_remaining": 123,
"discount_id": "<string>",
"discounts": [
{
"amount": 123,
"business_id": "<string>",
"code": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"discount_id": "<string>",
"metadata": {},
"position": 123,
"preserve_on_plan_change": true,
"restricted_to": [
"<string>"
],
"times_used": 123,
"type": "percentage",
"cycles_remaining": 123,
"expires_at": "2023-11-07T05:31:56Z",
"name": "<string>",
"subscription_cycles": 123,
"usage_limit": 123
}
],
"expires_at": "2023-11-07T05:31:56Z",
"payment_method_id": "<string>",
"scheduled_change": {
"addons": [
{
"addon_id": "<string>",
"name": "<string>",
"quantity": 123
}
],
"created_at": "2023-11-07T05:31:56Z",
"effective_at": "2023-11-07T05:31:56Z",
"id": "<string>",
"product_id": "<string>",
"quantity": 123,
"product_description": "<string>",
"product_name": "<string>"
},
"tax_id": "<string>"
}
}