Skip to Content
View as Markdown

인증

InfraIO Pay에는 인증 모델이 다른 두 가지 API 표면이 있습니다. 호출자가 누구인지에 맞는 것을 선택하세요.

표면경로 프리픽스대상인증
가맹점 B2B/b2b/v1/*가맹점 서버HMAC-SHA256 요청 서명
대시보드가맹점 대시보드에서 사용가맹점 대시보드 브라우저 세션Bearer JWT

이 페이지는 B2B 표면을 다룹니다. API 키 쌍으로 가맹점 서버에서 호출하는 표면입니다. 대시보드 표면은 InfraIO Pay 가맹점 대시보드에서 사용하며 공개 연동용 표면이 아닙니다.

항상 /b2b 프리픽스를 포함한 전체 경로로 요청을 보내고, 같은 경로로 서명하세요 (아래 참조).

엔드포인트

환경기본 URL
테스트https://api-dev.infraio.xyz
라이브https://api.infraio.xyz

동일한 URL 패턴 — 환경은 URL이 아닌 키 프리픽스(pk_test_… vs pk_live_…)로 제어됩니다.

키 쌍

가맹점 대시보드(Developers → API keys → + Add key)에서 두 가지 값을 받습니다.

  • 공개 키(pk_test_… 또는 pk_live_…) — 계정을 식별합니다. X-Client-ID로 전송됩니다. 브라우저 번들에 임베드해도 안전합니다(SDK가 이미 그렇게 합니다).
  • 비밀 키(sk_test_… 또는 sk_live_…) — HMAC 서명 키. 서버 전용입니다. 데이터베이스 패스워드처럼 다루세요.

비밀 키가 브라우저 번들, git 저장소, 로그 라인, 또는 공유 채팅에 노출된 경우 — 대시보드에서 즉시 폐기하세요. 폐기는 즉시 적용되며 오버랩 윈도우는 없습니다. 새 키를 발급하고 재배포하세요.

요청 서명

/b2b/v1/*에 대한 모든 호출은 세 개의 헤더를 포함합니다.

X-Client-ID: pk_live_70d0becbd7a53047b0dfe88a960d10ad X-Timestamp: 1715990400 X-Signature: 9a8b7c6d… (hex HMAC-SHA256)

서명은 정규 문자열에 대해 계산됩니다.

METHOD + "\n" + PATH + "\n" + TIMESTAMP + "\n" + BODY
  • METHOD — 대문자 HTTP 동사(POST, GET, …).
  • PATH — 호스트 없이, 쿼리 문자열 없이 /b2b 프리픽스가 포함된 요청 경로(예: /b2b/v1/checkout-sessions/quick). 프리픽스가 반드시 있어야 합니다. 쿼리 매개변수는 서명되지 않습니다 — GET …?cursor=…&limit=20의 경우, ?… 부분이 아닌 경로만 서명하세요.
  • TIMESTAMP — 10진수 문자열로 된 유닉스 초(예: "1715990400"), X-Timestamp와 정확히 일치해야 함.
  • BODY — 원본 요청 본문 바이트. GET/DELETE의 경우 빈 문자열.

비밀 키로 HMAC-SHA256 서명, hex로 출력:

import { createHmac } from "node:crypto"; function sign({ method, path, body, secret }: { method: string; path: string; body: string; secret: string; }) { const timestamp = Math.floor(Date.now() / 1000).toString(); const input = [method.toUpperCase(), path, timestamp, body].join("\n"); const signature = createHmac("sha256", secret).update(input).digest("hex"); return { timestamp, signature }; }

왜 HMAC이고 Bearer가 아닌가?

베어 Bearer 토큰 API는 모든 요청에서 유일한 시크릿을 회선을 통해 전송합니다. TLS-종료 프록시 로그 하나를 캡처한 누구나 계정 키를 얻게 됩니다. HMAC 서명은 시크릿이 절대 전송되지 않음을 의미합니다 — 일회용인 파생 서명(해당 정확한 요청 + 해당 정확한 분에 바인딩됨)만 전송됩니다.

트레이드오프: 모든 호출에 대해 서명을 계산해야 합니다. 아직 서버 SDK는 없지만, 위의 헬퍼는 언어당 약 15줄입니다.

타임스탬프 허용 오차

허용 오차는 ±5분(300초)입니다. 이 범위를 벗어난 요청은 401 invalid_signature로 거부됩니다. 두 가지 시사점:

  1. NTP로 서버 클록을 동기화하세요. 드리프트된 클록을 가진 장시간 실행 크론은 간헐적으로 실패합니다.
  2. 서명을 미리 계산하여 큐에 넣지 마세요. 요청이 재시도 큐에 5분 이상 머무르면 서명이 만료됩니다.

키 스코프

비밀 키는 다음 스코프 번들 중 하나 이상을 가집니다.

스코프의도된 사용
read주문, 세션, 환불 목록/읽기
write_order체크아웃 세션, 주문 생성
write_refund환불 발행, 환불 요청 토큰 발급
webhook_manage웹훅 엔드포인트 생성/업데이트/삭제

대시보드는 기본적으로 “전체 액세스” 키(네 가지 스코프 모두)를 발급합니다. Developers → API keys → + Add key에서 통합이 필요한 스코프만 체크하여 제한된 스코프 키를 발급할 수 있습니다.

스코프는 아직 강제되지 않습니다. 스코프는 키에 기록되고 대시보드에 표시되지만, 유효한 sk_… 키라면 가맹점의 모든 /b2b/v1/* 엔드포인트를 호출할 수 있습니다. 스코프를 보안 경계로 의존하지 마세요. 액세스를 제한하려면 키를 로테이션하거나 폐기하세요.

검증 실패

서명, X-Client-ID, 또는 타임스탬프가 유효하지 않으면 요청은 API에 도달하기 전에 **401 INVALID_SIGNATURE**로 거부됩니다. /b2b/v1/* 요청만 이 방식으로 서명됩니다. 웹훅은 별도의 방식을 사용합니다(아래 참조).

다음 단계

  • 오류 — 4xx/5xx 응답 형식.
  • 보안 → API 키 — 로테이션, 폐기, 시크릿 유출 시 조치.
  • 웹훅 → 서명 검증 — 다른 HMAC 방식을 사용합니다(헤더 X-Signature: sha256=…, X-Timestamp + "." + raw_body 서명, 24시간 로테이션 grace 윈도우 동안 선택적 X-Signature-Prev). 방식을 혼동하지 마세요 — 해시 알고리즘은 같지만 서명된 바이트와 시크릿 패밀리(whsec_… vs sk_…)가 다릅니다.