주문 Report: server API
Base URL: 당신의 s2s_endpoint_base (예: https://realry.com/api/v1/direct). 모든 request 는 JSON body 와 아래 3개 signature header 를 포함한 POST.
Request 서명
모든 호출에 3개 header:
| Header | Value |
|---|
X-Merchant-Key | 당신의 api_key |
X-Signature-Timestamp | 현재 unix time (초 단위의 정수) |
X-Signature | HMAC_SHA256(timestamp + body, hmac_secret), hex 형식 |
Signature 만들기: timestamp 를 취하고, 정확한 JSON body 를 어떤 공백이나 구분자도 없이 바로 뒤에 붙여서, 그 string 을 hmac_secret 으로 HMAC-SHA256.
JSON body 를 한 번 serialize 하고, 그 exact text 를 서명하고, 그 exact text 를 보내세요. 서명 후 body 를 다시 encode 하면 (key 순서만 바꿔도) signature 가 맞지 않음.
서버가 check 하는 것 — 실패 시 401:
- 3개 header 전부 포함.
- Timestamp 는 정수이며 우리 서버 clock 과 5분 이내.
api_key 가 active.
- Signature 매칭.
당신의 key 는 계정에 tied 되어 있어서 body 에 seller 를 많이하지 않음 — 우리는 이미 당신음을 압니다.
4개 Event
주문의 생애을 이 호출들로 report. 모두 merchant_order_id (당신의 order id) 와 unique event_id (아래 Safe retries 참고) 가 필요.
1. 주문 완료 — POST /conversions
결제 완료 순간 전송 (card capture, 또는 가상계좌 주문의 경우 입금 확인 — 아래 가상계좌 주문 참고).
{
"merchant_order_id": "order-1",
"event_id": "evt-1",
"amount": 49900,
"currency": "KRW",
"cb_aev": "ABC123",
"product_name": "Silk Blouse",
"items": [{ "item_id": "sku-7", "name": "Silk Blouse", "price": 49900, "quantity": 1 }]
}
| Field | 필수 | Note |
|---|
merchant_order_id | yes | 당신의 order id (pixel transaction_id 과 동일) |
event_id | yes | 호출당 unique; retry 에 안전하게 |
amount | yes | 주문 총액; 0 이상의 숫자 |
currency | yes | 3자리 코드, 예: KRW |
cb_aev | no | 저장해둔 click id; 빼면 크리에이터에게 credit 되지 않음 |
product_name | no | 크리에이터 dashboard 에 표시; 없으면 items[0].name, 그것도 없으면 빈칸 |
items | no | Line item, 당신의 기록용 |
sub_id | no | 당신의 click/tracking ref — 우리가 어디서나 echo 하므로 reconciliation 에 유용 |
Response:
{
"data": {
"merchant_order_id": "order-1",
"transaction_id": "stylmatch:<your_seller_id>:order-1",
"status": "CONFIRMED",
"net_amount": 49900,
"refunded_amount": 0,
"currency": "KRW"
}
}
net_amount 은 주문 총액 에서 refund 를 뭐 직수. transaction_id 는 우리 내부 reference — parse 할 필요 없으메; 항상 당신의 merchant_order_id 로 주문 매칭.
2. Partial refund — POST /conversions/partial
주문을 refund_amount 만큼 감소 (부분 취소 또는 반품).
{ "merchant_order_id": "order-1", "event_id": "evt-2", "refund_amount": 10000 }
Status 는 PARTIALLY_CANCELLED 로 바뀌고 net_amount 감소. refund_amount 는 0 과 현재 net_amount 사이의 숫자여야 함.
3. Full cancel — POST /conversions/cancel
{ "merchant_order_id": "order-1", "event_id": "evt-3" }
net_amount 를 0 으로, status CANCELLED, commission reverse.
4. 이 주문은 credit 하지 마 — POST /conversions/decline
당신이 자체 유료 채널이 실제로 판매를 이김 (크리에이터가 아니라) 를 판단했을 때 사용. Declined 주문은 settlement 에서 떨어지며 invoice 안 됨.
{ "merchant_order_id": "order-1", "event_id": "evt-4", "reason": "own_google_ads_last_click" }
Status 는 DECLINED, net_amount 0. reason 은 당신 기록용 free-text.
Safe retries — event_id
모든 호출에 unique event_id 사용. Request timeout 이서 retry 하면 같은 event_id 재사용 — 우리가 인지하고 double-count 하지 않음. Retry 는 항상 안전.
가상계좌 주문
가상계좌 (bank transfer) 결제는 고객이 입금해야 진짜가 됨:
- 주문 생성 시점에서는 order report 보내지 말 것.
- PG 의 입금 확인 webhook (PortOne / Toss / NICE) fire 될 때 보내세요. 그 순간이
POST /conversions 호출 타이밍.
- 기한이 지나도 입금이 없으면 그냥 보내지 마세요. Cancel 호출 불필요 — 우리가 모르는 주문은 절대 settle 되지 않음.