하루페이는 하루 머니를 충전해 결제에 사용할 수 있는 간편 결제를 서비스입니다. 하루 서비스 회원이라면 하루 머니가 연동된 서비스에서 하루 페이머니로 결제할 수 있습니다.
![]() |
![]() |
|---|---|
![]() |
![]() |
![]() |
|---|---|
![]() |
![]() |
docker-compose up
브라우저에서 직접 payments의 POST /api/payment/prepare를 호출하는 대신, merchant backend가 가결제를 생성한 뒤 paymentId를 SDK에 넘기거나 SDK가 merchant backend의 prepareUrl을 호출하도록 사용하는 방식을 권장합니다.
이 방식의 장점:
- merchant API key를 브라우저에 노출하지 않음
- merchant가 주문 검증과 가결제 생성을 직접 통제할 수 있음
- SDK는 결제창 오픈과 완료 후 URL 이동 계약에 집중할 수 있음
<script src="https://example.com/harupay.js"></script>
<script>
const haruPay = HaruPay.create({
checkoutUrl: 'https://payments.example.com',
prepareUrl: 'https://merchant.example.com/api/payments/prepare',
successUrl: 'https://merchant.example.com/payments/success',
failureUrl: 'https://merchant.example.com/payments/failure'
});
</script>SDK URL 계약:
successUrl에는 최소한requestId,paymentId,orderId,requestPrice가 query parameter로 포함됩니다.failureUrl에는 최소한errorCode,message,orderId가 query parameter로 포함됩니다.- merchant는 해당 URL에서 화면 전환, 백엔드 검증, 후속 처리 로직을 직접 수행합니다.
- popup 결제 흐름에서는 opener 페이지가 아니라 popup 창이
successUrl/failureUrl로 이동하는 것을 기본 동작으로 사용합니다. - 권장 방식은
successUrl을 merchant backend endpoint로 두고, 이 endpoint에서 결제 요청 파라미터를 검증한 뒤 confirm을 시작하는 것입니다. - 주문 완료 처리는
successUrl도착 시점이 아니라 confirm 이후 최종SUCCEEDED결과를 확인한 뒤 수행해야 합니다.
haruPay.open({
orderId: 'ORDER-001',
productName: 'Wireless Headphone',
amount: 10000
});prepareUrl 응답은 아래 형식을 따라야 합니다.
{
"paymentId": "d2c98b67-bf7d-4e59-83c3-1b2f905b7b35"
}const prepared = await fetch('/api/payments/prepare', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
orderId: 'ORDER-001',
productName: 'Wireless Headphone',
requestPrice: 10000
})
}).then((response) => response.json());
await haruPay.open({ paymentId: prepared.paymentId });권장 계약:
- 가결제 생성은 merchant backend가 담당
- SDK는
paymentId를 받아 결제창만 오픈하거나, merchant backend의prepareUrl을 호출 - SDK 성공/실패 후처리는
successUrl/failureUrl기반으로 제어 - 주문 성공 여부는 merchant backend가 최종 payment status로 확인
POST /api/payment/prepare
POST
| 키 | 값 | 설명 |
|---|---|---|
Authorization |
apiKey <api_key> |
클라이언트의 API 키 |
X-PAY-CLIENT-ID |
<client_id> |
클라이언트 ID |
Idempotency-Key |
<custom_key> |
멱등성 키 (선택, 최대 300자) |
application/json 형식으로 아래와 같은 JSON 데이터를 전달해야 합니다.
| 필드 이름 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
orderId |
String |
✔️ | 주문 ID |
requestPrice |
BigDecimal |
✔️ | 요청 결제 금액 |
productName |
String |
✔️ | 제품 이름 |
{
"orderId": "ORDER12345",
"requestPrice": 10000.00,
"productName": "Wireless Headphone"
}{
"paymentId": "d2c98b67-bf7d-4e59-83c3-1b2f905b7b35"
}POST /api/payment/confirm
POST
| 키 | 값 | 설명 |
|---|---|---|
Authorization |
apiKey <api_key> |
클라이언트의 API 키 |
X-PAY-CLIENT-ID |
<client_id> |
클라이언트 ID |
Content-Type |
application/json |
요청 본문 타입 |
Idempotency-Key |
<custom_key> |
멱등성 키 (선택, 최대 300자) |
application/json 형식으로 아래와 같은 JSON 데이터를 전달해야 합니다.
| 필드 이름 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
paymentId |
UUID |
✔️ | 결제 ID |
{
"paymentId": "a2d8bc7d-0b07-47a1-b3b9-48578de8a63f"
}응답 본문은 없으며, 요청이 성공하면 HTTP 200 OK 상태 코드가 반환됩니다.
Idempotency-Key는 헤더로 전달합니다.- 길이는 최대 300자입니다.
- UUID, ULID, 주문번호 조합 등 클라이언트가 원하는 문자열을 사용할 수 있습니다.
- 현재는 계약만 먼저 열어둔 상태이며, 실제 멱등성 처리 정책은 이후 단계에서 강화합니다.
GET /api/payment-result/subscribe
GET
| 키 | 값 | 설명 |
|---|---|---|
Authorization |
apiKey <api_key> |
클라이언트의 API 키 |
Last-Event-ID |
<last_event_id> |
마지막 이벤트 ID (옵션) |
| 필드 이름 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
paymentId |
UUID |
✔️ | 결제 ID |
GET /api/payment-result/subscribe?paymentId=d2c98b67-bf7d-4e59-83c3-1b2f905b7b35 HTTP/1.1
Authorization: apiKey <api_key>
Last-Event-ID: "12345"이 API는 Server-Sent Events (SSE) 방식으로 실시간 스트리밍 데이터를 제공합니다. 응답 내용은 PaymentConfirmResponse 형식에 맞춰 제공됩니다.
{
"requestId": "cfa8d3ed-d9b2-4207-9bc2-85c16a4d632d",
"orderId": "abc123",
"requestMemberId": "fbb1267a-d836-4fd1-96db-774e567d03d8",
"requestPrice": 500000,
"clientId": "bcd7991e-cb21-4b99-9013-ef83b10f450d",
"paymentStatus": 1,
"approvedAt": "2025-03-08T12:34:56Z"
}requestId: 요청 ID (UUID 형식)orderId: 주문 IDrequestMemberId: 요청한 사용자 ID (UUID 형식)requestPrice: 결제 요청 금액 (BigDecimal 형식)clientId: 클라이언트 ID (UUID 형식)paymentStatus: 결제 상태 (예:1= 승인됨,0= 실패 등)approvedAt: 결제 승인 시간 (ISO 8601 형식)
이 API는 실시간으로 결제 결과를 스트리밍하여 클라이언트에 전달합니다.






