웹훅
Updated:
폴링 대신, HTTPS 엔드포인트에서 주문 관련 이벤트를 수신할 수 있습니다. 웹훅은 다음과 동일한 이벤트를 전달합니다. 순서별 이벤트. 이벤트 로그는 웹훅 유무와 관계없이 계속 사용할 수 있으므로, 언제든지 폴링 방식으로 대체할 수 있습니다.
설정
응답 내용은 다음과 같습니다.
webhook_secret(whsec_…) 한 번만. 이를 저장해 두세요: 모든 웹훅에 서명하는 데 사용됩니다.변경
callback_url새로운 비밀번호를 발급합니다. 이전 비밀번호는 24시간 동안 웹훅 서명에 계속 사용됩니다. 이 기간 동안X-PS-Signature서명이 두 개 있습니다.
요청
속성 | 가치 |
|---|---|
방법 |
|
제목 |
|
본문 | 다음과 같은 하나의 이벤트: 이벤트 순서; |
성공 | 모든 |
납품 | 적어도 한 번, 순서는 보장되지 않습니다. 중복을 제거하려면 다음을 적용하십시오. |
POST /hooks/proxy HTTP/1.1
Host: agent.example.com
Content-Type: application/json; charset=utf-8
User-Agent: ProxySeller-Webhooks/1
X-PS-Timestamp: 1762077838
X-PS-Signature: v1=5f0c2a…9e
{"event_id":"evt_01JZ8QA2C4E6G8J0K2M4P6R8T0","type":"order.active","created_at":"2026-11-02T10:03:58Z","api_version":"v1","order_id":"ord_01JZ8Q7K5N2R4T6V8X0Z2B4D6F","wallet":"0x857b06519e91e3a54538791bdbb0e22373e36b66","attempt":1,"data":{"lines":[{"line_id":"1","status":"active","delivered":2,"qty":2}],"expires_at":"2026-12-02T23:59:59Z"}}서명 확인
X-PS-Signature: v1=hex(HMAC-SHA256(key, timestamp + "." + raw_body))
key— 전체의 바이트(UTF-8)webhook_secretstring, 다음을 포함하여whsec_접두사.timestamp— 의 가치X-PS-Timestamp, 유닉스 초.raw_body— JSON 파싱을 수행하기 전, 수신된 그대로의 본문.비공개 변경 후 24시간 동안 헤더는
v1=<current>,v1=<previous>: 해당 항목 중 하나라도 일치하면 요청을 수락하십시오.시간 표시가 귀하의 시계와 300초 이상 차이가 나는 요청은 거부하십시오.
파이썬
import hashlib
import hmac
import time
def verify(secret: str, timestamp: str, signature_header: str, raw_body: bytes, tolerance: int = 300) -> bool:
if abs(time.time() - int(timestamp)) > tolerance:
return False
expected = hmac.new(secret.encode(), timestamp.encode() + b"." + raw_body, hashlib.sha256).hexdigest()
candidates = [part.strip()[3:] for part in signature_header.split(",") if part.strip().startswith("v1=")]
return any(hmac.compare_digest(expected, candidate) for candidate in candidates)Node.js
import crypto from 'node:crypto';
function verify(secret, timestamp, signatureHeader, rawBody, toleranceSeconds = 300) {
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > toleranceSeconds) return false;
const expected = crypto.createHmac('sha256', secret).update(`${timestamp}.`).update(rawBody).digest('hex');
return signatureHeader.split(',').map((s) => s.trim()).filter((s) => s.startsWith('v1='))
.some((s) => s.length === expected.length + 3
&& crypto.timingSafeEqual(Buffer.from(s.slice(3)), Buffer.from(expected)));
}재시도
규칙 | 가치 |
|---|---|
첫 번째 시도 | 사건 발생 후 30초가 지난 시점부터 |
재시도 | 1분, 5분, 30분, 2시간, 6시간, 12시간, 24시간 후: 약 44.6시간 동안 8회 시도 |
너무 오래된 내용 | 약 45.6시간 이상 지난 이벤트는 더 이상 전송되지 않습니다. |
회로 차단기 | 3회 연속 실패 시, 해당 주문의 나머지 이벤트들은 다음 시도를 기다립니다. |
비활성화 | 이벤트의 마지막 시도가 실패하고, 해당 이벤트가 생성된 이후 해당 URL이 웹훅을 수신하지 않은 경우, 해당 URL로의 전송이 비활성화됩니다. 주문 자체에는 영향을 미치지 않습니다. |
비활성화된 URL을 활성화하려면 다음을 포함하여 다시 전송하십시오. 업데이트 순서: 동일한 URL은 시간당 최대 한 번만 허용되며, 새로운 URL은 언제든지 가능합니다. 놓친 이벤트는 항상 이벤트 순서.
callback_url 규칙
견적서 발행 시점에 확인되었으며, PATCH. 이를 위반할 경우 400 invalid_request:
규칙 | 상세 정보 |
|---|---|
인쇄 가능한 ASCII, 최대 2048자 |
|
|
|
URL에 로그인 정보나 비밀번호가 포함되어서는 안 됩니다. |
|
단편 없음 |
|
443번 포트 전용 |
|
공개 DNS 이름, 표준 IPv4 주소 또는 괄호 안에 표기된 IPv6 주소 |
|
호스트의 모든 주소는 공개되어 있습니다. |
|
서비스 자체의 호스트가 아닙니다. |
|
모든 전달 전에 DNS를 다시 확인하며, 요청은 확인된 주소로만 전송됩니다.