구독 계약의 회차 금액 조정 항목을 한번에 변경하는 API예요. 지정한 회차(duration)의 조정 항목을 요청한 항목으로 모두 대체해요.
API 엔드포인트
관리자 권한 필요
이 API는 Basic 인증과 supervisor:order_subscription_adjustment_update scope가 필요해요.
전체 대체 방식
지정한 회차(duration, 기본 1)의 기존 조정 항목이 모두 삭제되고 요청한 항목으로 대체돼요. 다른 회차의 조정과 무제한(is_unlimited) 조정은 그대로 남아요. 수정이 아닌 전체 교체예요. 특정 항목만 삭제하려면 조정 항목 삭제를 사용해요.
요청 파라미터
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
order_subscription_id |
String | 필수 | 구독 계약 고유 번호 (URL 경로) |
duration |
Integer | 선택 | 대체 대상 회차. 요청 최상위 파라미터예요 (기본 1) |
adjustments |
Array | 필수 | 해당 회차를 대체할 조정 항목 배열 |
└─ name |
String | 필수 | 조정 항목명 |
└─ price |
Integer | 필수 | 조정 금액 |
└─ tax_free_price |
Integer | 선택 | 면세 금액 |
└─ type |
Integer | 필수 | 조정 타입 숫자(아래 표의 값). 항목 안에 duration 을 넣어도 무시돼요 |
코드 예제
curl -X PUT "https://api.bootapi.com/v1/order_subscriptions/{order_subscription_id}/adjustments" \
-H "Authorization: Basic {base64(client_key:secret_key)}" \
-H "Content-Type: application/json" \
-d '{
"duration": 1,
"adjustments": [
{
"name": "설치비",
"price": 50000,
"type": 2
},
{
"name": "프로모션 할인",
"price": -10000,
"type": 1
}
]
}'bashconst { BootpayCommerce } = require('@bootpay/backend-js');
const commerce = new BootpayCommerce({
client_key: '{client_key}',
secret_key: '{secret_key}'
});
const response = await commerce.orderSubscriptionBill.adjustment.update('687a1b2c3d4e5f6789012345', {
duration: 1,
adjustments: [
{ name: '설치비', price: 50000, type: 2 },
{ name: '프로모션 할인', price: -10000, type: 1 }
]
});
console.log(response);javascriptfrom bootpay_backend.commerce import BootpayCommerce
commerce = BootpayCommerce('{client_key}', '{secret_key}')
response = commerce.order_subscription_adjustment_update('687a1b2c3d4e5f6789012345', {
'duration': 1,
'adjustments': [
{'name': '설치비', 'price': 50000, 'type': 2},
{'name': '프로모션 할인', 'price': -10000, 'type': 1}
]
})
print(response)pythonuse Bootpay\ServerPhp\BootpayCommerceApi;
$commerce = new BootpayCommerceApi("{client_key}", "{secret_key}");
$response = $commerce->orderSubscriptionAdjustmentUpdate('687a1b2c3d4e5f6789012345', [
'duration' => 1,
'adjustments' => [
['name' => '설치비', 'price' => 50000, 'type' => 2],
['name' => '프로모션 할인', 'price' => -10000, 'type' => 1]
]
]);
print_r($response);phpimport kr.co.bootpay.store.BootpayStore;
import kr.co.bootpay.store.model.request.TokenPayload;
import kr.co.bootpay.store.model.response.BootpayStoreResponse;
import kr.co.bootpay.store.model.request.orderSubscriptionAdjustment.OrderSubscriptionAdjustmentUpdateParams;
import kr.co.bootpay.store.model.pojo.SOrderSubscriptionAdjustment;
import java.util.Arrays;
TokenPayload tokenPayload = new TokenPayload("{client_key}", "{secret_key}");
BootpayStore commerce = new BootpayStore(tokenPayload).withToken();
SOrderSubscriptionAdjustment adj1 = new SOrderSubscriptionAdjustment();
adj1.name = "설치비";
adj1.price = 50000.0;
adj1.type = 2;
SOrderSubscriptionAdjustment adj2 = new SOrderSubscriptionAdjustment();
adj2.name = "프로모션 할인";
adj2.price = -10000.0;
adj2.type = 1;
OrderSubscriptionAdjustmentUpdateParams params = new OrderSubscriptionAdjustmentUpdateParams();
params.orderSubscriptionId = "687a1b2c3d4e5f6789012345";
params.duration = 1;
params.adjustments = Arrays.asList(adj1, adj2);
BootpayStoreResponse response = commerce.orderSubscriptionAdjustment.update(params);
System.out.println(response);javarequire 'bootpay'
commerce = BootpayStore::RestClient.new(client_key: '{client_key}', secret_key: '{secret_key}')
response = commerce.order_subscription_adjustment_update(
order_subscription_id: '687a1b2c3d4e5f6789012345',
duration: 1,
adjustments: [
{ name: '설치비', price: 50000, type: 2 },
{ name: '프로모션 할인', price: -10000, type: 1 }
]
)
puts responserubycommerce := bootpay.NewCommerceApi("{client_key}", "{secret_key}")
response, err := commerce.OrderSubscriptionAdjustmentUpdate("687a1b2c3d4e5f6789012345", map[string]interface{}{
"duration": 1,
"adjustments": []map[string]interface{}{
{"name": "설치비", "price": 50000, "type": 2},
{"name": "프로모션 할인", "price": -10000, "type": 1},
},
})
fmt.Println(response)govar commerce = new BootpayCommerceApi("{client_key}", "{secret_key}");
var response = await commerce.OrderSubscriptionAdjustmentUpdate("687a1b2c3d4e5f6789012345", new {
duration = 1,
adjustments = new[] {
new { name = "설치비", price = 50000, type = 2 },
new { name = "프로모션 할인", price = -10000, type = 1 }
}
});
Console.WriteLine(response);csharp응답
성공 응답
변경이 반영된 구독 계약 상세 전체를 돌려줘요. 아래는 조정 항목 부분만 추린 예시예요.
{
"order_subscription_id": "687a1b2c3d4e5f6789012345",
"order_subscription_adjustments": [
{
"order_subscription_adjustment_id": "6965fc104cb8149d07712533",
"name": "설치비",
"price": 50000,
"tax_free_price": 0,
"type": "setup_price",
"duration": 1,
"is_unlimited": false
},
{
"order_subscription_adjustment_id": "6965fc104cb8149d07712534",
"name": "프로모션 할인",
"price": -10000,
"tax_free_price": 0,
"type": "discount",
"duration": 1,
"is_unlimited": false
}
]
}json응답 파라미터
| 파라미터 | 타입 | 설명 |
|---|---|---|
| order_subscription_id | String | 구독 계약 ID |
| order_subscription_adjustments | Array | 계약에 걸린 전체 조정 항목 목록 (다른 회차·무제한 조정 포함) |
상태·유형 값은 문자열이에요
응답의 status 같은 코드값은 정수가 아니라 문자열(enum)로 내려와요. 전체 목록은 커머스 Enum에서 확인해요.
조정 타입 (type)
| 값 | 키 | 설명 |
|---|---|---|
1 |
discount |
회차별 할인 적용 |
2 |
setup_price |
추가금액 (설치비 등) |
3 |
cycle_discount |
주기 할인 적용 |
4 |
cycle_additional_fee |
추가 비용 적용 |
5 |
recurring_fee |
매회차 추가비용 (모든 할인 적용 후) |
10 |
coupon |
구독 상품 금액 쿠폰 |
11 |
shipping_coupon |
배송비 쿠폰 |
에러 코드
공통 에러
인증·권한 관련 에러는 에러 코드표를 참고해요.
| 코드 | 메시지 | 대처 방법 |
|---|---|---|
ORDER_SUBSCRIPTION_INVALID |
구독결제 정보가 올바르지 않아요. | 구독 계약 ID를 확인해요 |
SUBSCRIPTION_ADJUSTMENT_PAYMENT_COMPLETED |
이미 결제가 완료된 회차예요. 가격조정을 할 수 없어요. | 미결제 회차에 대해서만 조정해요 |
SUBSCRIPTION_ADJUSTMENT_NEGATIVE_PRICE |
회차 가격 조정으로 인해 최종 결제 금액이 음수가 될 수 없어요. | 조정 금액을 다시 확인해요 |
