웹훅

CheckoutOS의 실시간 이벤트 알림

마지막 업데이트: 2025-01-16

웹훅을 사용하면 CheckoutOS에서 이벤트가 발생할 때 실시간 알림을 받을 수 있어요. API를 반복해서 조회하는 대신 이벤트 발생 시 웹훅이 서버로 데이터를 전송해요.

사용 가능한 이벤트

웹훅 이벤트

  • upsell.accepted — 고객이 추가 판매 제안을 수락했어요
  • upsell.declined — 고객이 추가 판매 제안을 거절했어요
  • bundle.purchased — 번들을 구매했어요
  • experiment.concluded — A/B 테스트가 유의성에 도달했어요
  • order.edited — 고객이 주문을 수정했어요
  • order.cancelled — 고객이 주문을 취소했어요
  • subscription.created — 구독 추가 판매가 전환되었어요

웹훅 만들기

1

웹훅으로 이동

CheckoutOS → Settings → Webhooks로 이동하세요.
2

엔드포인트 추가

"Add Webhook Endpoint"를 클릭하세요.
3

URL 입력

이벤트를 수신할 HTTPS URL을 입력하세요.
4

이벤트 선택

구독할 이벤트를 선택하세요.
5

저장

저장하고 서명 시크릿을 기록해 두세요.
API로 웹훅 만들기
curl -X POST "https://api.chargezen.com/v1/webhooks" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://yourserver.com/webhooks/checkoutos",
    "events": ["upsell.accepted", "bundle.purchased"],
    "enabled": true
  }'

# Response
{
  "id": "wh_123",
  "url": "https://yourserver.com/webhooks/checkoutos",
  "events": ["upsell.accepted", "bundle.purchased"],
  "signing_secret": "whsec_abc123...",
  "enabled": true
}

웹훅 페이로드

upsell.accepted

추가 판매 수락 이벤트
{
  "id": "evt_123456",
  "type": "upsell.accepted",
  "created_at": "2025-01-16T14:30:00Z",
  "data": {
    "upsell_id": "upsell_abc",
    "upsell_name": "Premium Add-On",
    "order_id": "order_789",
    "shopify_order_id": "5678901234",
    "customer_id": "cust_456",
    "product": {
      "id": "prod_xyz",
      "title": "Premium Widget",
      "variant_id": "var_123",
      "price": 29.99
    },
    "discount": {
      "type": "percentage",
      "value": 15,
      "amount": 4.50
    },
    "final_price": 25.49
  }
}

bundle.purchased

번들 구매 이벤트
{
  "id": "evt_234567",
  "type": "bundle.purchased",
  "created_at": "2025-01-16T15:00:00Z",
  "data": {
    "bundle_id": "bundle_def",
    "bundle_name": "Skincare Starter Kit",
    "bundle_type": "fixed",
    "order_id": "order_890",
    "products": [
      { "id": "prod_a", "title": "Cleanser", "quantity": 1 },
      { "id": "prod_b", "title": "Toner", "quantity": 1 },
      { "id": "prod_c", "title": "Moisturizer", "quantity": 1 }
    ],
    "original_price": 89.97,
    "bundle_price": 71.98,
    "savings": 17.99
  }
}

order.edited

주문 수정 이벤트
{
  "id": "evt_345678",
  "type": "order.edited",
  "created_at": "2025-01-16T15:30:00Z",
  "data": {
    "order_id": "order_901",
    "shopify_order_id": "6789012345",
    "edit_type": "add_items",
    "changes": {
      "items_added": [
        { "product_id": "prod_new", "quantity": 1, "price": 19.99 }
      ],
      "items_removed": [],
      "quantity_changes": []
    },
    "amount_changed": 19.99,
    "new_total": 109.98
  }
}

웹훅 검증

모든 웹훅에는 검증용 서명 헤더가 포함돼요.

Node.js 검증
const crypto = require('crypto');

function verifyWebhook(payload, signature, secret) {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(payload, 'utf8')
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(`sha256=${expectedSignature}`)
  );
}

// Express middleware
app.post('/webhooks/checkoutos', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-checkoutos-signature'];

  if (!verifyWebhook(req.body, signature, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }

  const event = JSON.parse(req.body);
  // Handle event...

  res.status(200).send('OK');
});
Python 검증
import hmac
import hashlib

def verify_webhook(payload: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode('utf-8'),
        payload,
        hashlib.sha256
    ).hexdigest()

    return hmac.compare_digest(
        f'sha256={expected}',
        signature
    )

# Flask example
@app.route('/webhooks/checkoutos', methods=['POST'])
def handle_webhook():
    signature = request.headers.get('X-CheckoutOS-Signature')

    if not verify_webhook(request.data, signature, WEBHOOK_SECRET):
        return 'Invalid signature', 401

    event = request.get_json()
    # Handle event...

    return 'OK', 200
항상 검증하세요

처리하기 전에 항상 웹훅 서명을 검증하세요. 공격자가 엔드포인트에 가짜 이벤트를 보내는 것을 방지해요.

재시도 정책

웹훅 전달에 실패하면 지수적으로 간격을 늘려 재시도해요.

재시도 일정
{
  "retry_policy": {
    "max_attempts": 5,
    "schedule": [
      { "attempt": 1, "delay": "immediately" },
      { "attempt": 2, "delay": "5 minutes" },
      { "attempt": 3, "delay": "30 minutes" },
      { "attempt": 4, "delay": "2 hours" },
      { "attempt": 5, "delay": "24 hours" }
    ],
    "success_codes": [200, 201, 202, 204],
    "timeout": "30 seconds"
  }
}

웹훅 테스트

실제 운영 전에 웹훅 엔드포인트를 테스트하세요.

테스트 이벤트 전송
curl -X POST "https://api.chargezen.com/v1/webhooks/wh_123/test" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "event_type": "upsell.accepted"
  }'

웹훅 로그

대시보드나 API에서 웹훅 전달 이력을 확인해요.

웹훅 로그 조회
curl -X GET "https://api.chargezen.com/v1/webhooks/wh_123/logs" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Response
{
  "data": [
    {
      "id": "log_123",
      "event_id": "evt_456",
      "event_type": "upsell.accepted",
      "status": "delivered",
      "response_code": 200,
      "duration_ms": 245,
      "created_at": "2025-01-16T14:30:00Z"
    }
  ]
}

권장 방법

웹훅 팁
  • 빠르게 응답해요 — 30초 이내에 200을 반환하세요
  • 비동기로 처리해요 — 백그라운드 처리를 위해 이벤트를 큐에 넣으세요
  • 중복을 처리해요 — 이벤트는 여러 번 전달될 수 있어요
  • 서명을 검증해요 — 처리 전에 항상 검증하세요
  • 실패를 모니터링해요 — 전달 실패 알림을 설정하세요

관련 주제

이 페이지가 도움이 되었나요?

도움이 더 필요하신가요? 고객 지원 문의