유효한 결제 알림이라도 같은 주문을 두 번 이행하게 해서는 안 됩니다. 암호화폐 결제 Webhook에는 별개의 두 가지 보호 장치가 필요합니다. 먼저 이벤트를 보낸 주체를 확인하고, 그다음에는 반복 실행해도 업무상 효과가 중복되지 않게 해야 합니다. 서명은 첫 번째 문제를, 멱등성은 두 번째 문제를 해결합니다.
이 가이드는 일회성 디지털 상품 구매, 라이선스 또는 계정 잔액 충전을 Yolfi와 연동하는 개발자를 위한 문서입니다. 기본 Webhook 형식과 권장 애플리케이션 설계를 설명하며, 완성된 주문 이행 서비스를 제공하는 것은 아닙니다. 구독의 경우 이용 권한이 구독 수명 주기에도 좌우되므로 일회성 주문 규칙을 모든 갱신에 그대로 적용해서는 안 됩니다.
진짜 Webhook도 중복 이행을 일으킬 수 있는 이유
수신기가 이벤트를 정상적으로 저장했어도 HTTP 응답이 유실될 수 있습니다. 그러면 발신자는 다시 전송합니다. 작업 프로세스가 이용 권한을 부여한 뒤 완료를 기록하기 전에 중단될 수도 있습니다. 어느 경우도 고객이 두 번째로 결제했다는 뜻은 아닙니다.
Yolfi의 Webhook 이벤트 참조 문서는 최소 한 번 전달하는 방식과 여러 엔드포인트의 독립적인 재시도를 설명합니다. 첫 번째 전달을 아직 처리하는 중에도 동일한 이벤트가 다시 도착할 수 있다는 전제로 설계하세요. 특정 재시도 일정에 의존하거나 알림이 항상 생성 순서대로 애플리케이션에 도착한다고 가정하지 마세요.
다음 세 가지 식별자를 구분하세요.
| 식별자 | 식별 대상 | 권장 제어 방식 |
|---|---|---|
서명된 이벤트의 id |
반복 전달을 포함한 제공업체의 단일 이벤트 | 제공업체, 조직, 환경 범위 내에서 고유한 이벤트 레코드 유지 |
| 청구서 또는 결제 참조 | 한 번의 결제 시도 | 해당 상거래 주문과의 연결 관계 저장 |
| 업무상 주문 참조 | 고객이 받아야 할 것 | 해당 주문에 대해 고유한 이행 작업 보장 |
이벤트 중복 제거만으로는 충분하지 않습니다. 한 주문에 대해 성공한 두 결제 시도는 서로 다른 이벤트 ID를 가질 수 있습니다. 주문 단위의 보호 장치는 추가 입금 건을 별도로 검토하는 동안 라이선스나 잔액이 두 번 지급되는 것을 막습니다.
필드를 신뢰하기 전에 원본 요청부터 검증하기
최신 Yolfi 서명 지침을 따르세요. 기본 요청은 해당 엔드포인트의 서명 비밀키로 원본 요청 본문에 HMAC-SHA256을 적용하고 Base64로 인코딩한 X-Yolfi-Signature를 사용합니다. 조직 API 키는 Webhook 비밀키가 아닙니다.
JSON 미들웨어가 본문을 변경하기 전에 원본을 확보하세요. 서명을 계산한 뒤 상수 시간 비교 함수로 대조하고, 서명이 없거나 형식이 잘못되었으면 업무 작업을 실행하지 말고 거부하세요. 서명 비밀키는 비밀정보 관리 서비스나 보호된 환경 설정에 보관하고, 소스 파일이나 고객 지원 로그에 남기지 마세요.
검증을 마친 뒤에만 페이로드를 파싱하고 유효성을 확인하세요. 중복 제거에는 서명된 페이로드의 id를 사용합니다. X-Yolfi-Event-ID는 편의를 위한 복사본이지 별도로 서명된 값이 아닙니다. 사용한다면 페이로드 ID와 일치해야 합니다. 수신 엔드포인트를 예상 조직에 연결하고, orgId가 있으면 검증하세요. 사용자가 제공한 메타데이터로 테넌트 권한을 결정해서는 안 됩니다.
유효한 서명이 있다고 해서 이전 전달이 새로운 이벤트가 되지는 않습니다. 처리한 이벤트 ID는 여전히 보관해야 합니다. Yolfi 문서의 서명 방식은 타임스탬프 기반의 최신성 검사가 아니므로, HMAC 검증만으로 재전송 공격을 막는다고 설명해서는 안 됩니다.
먼저 저장하고 수신을 확인한 뒤 비동기로 처리하기
영구 수신함을 사용하세요. 인증된 이벤트와 처리 상태를 기록하는 애플리케이션 테이블입니다. 이벤트 삽입에는 데이터베이스의 고유성 제약을 적용하세요. 별도로 “이미 있는가?”를 확인한 다음 보호 없이 삽입해서는 안 됩니다. 동시 요청은 둘 다 그 검사를 통과할 수 있습니다.
영구 저장을 완료한 뒤에는 신속하게 200 OK를 반환하세요. 인증된 중복 이벤트가 이미 저장되어 있는 경우도 마찬가지입니다. 저장에 실패하면 이벤트를 수락했다고 응답하지 마세요. 빠르게 응답한 뒤 메모리상의 작업을 실행하는 방식은 영속성을 보장하지 않습니다. 재시작하면 애플리케이션이 보관한 유일한 사본을 잃을 수 있습니다.
이후 작업 프로세스가 저장된 이벤트를 불러와 주문 연결 관계를 검증하고 업무 상태를 변경할 수 있습니다. 재시도 횟수, 다음 조치, 경보 담당자를 기록해 실패 작업을 계속 추적하세요. 이벤트 본문에 고객 정보가 포함될 수 있으므로 필요한 페이로드 데이터만 접근이 제한된 저장소에 보관하세요.
결제 확인과 올바른 주문 연결을 이행 조건으로 삼기
Yolfi Webhook 가이드는 payment.confirmed를 주된 주문 이행 트리거로 명시합니다. invoice.created는 청구서가 만들어졌다는 뜻이지 고객이 결제했다는 뜻이 아닙니다. 브라우저 리디렉션이나 화면 캡처는 검증된 서버 측 결제 확인을 대신할 수 없습니다.
이벤트를 서버에 저장된 주문과 연결하세요. 기본 흐름에서 독립적인 API Checkout 이벤트는 checkoutSessionId와 merchantOrderId를 포함하면서 paylinkId는 없을 수 있습니다. Paylink ID가 없다는 이유만으로 유효한 독립 구매를 거부하지 마세요. 반대로 재사용 가능한 Paylink ID만으로는 구매자의 주문을 고유하게 식별할 수 없습니다.
제공을 승인하기 전에 예상 조직, 환경, 결제 시도와 거래 금액의 맥락을 확인하세요. 문서의 amount는 결제 토큰 단위로 표시된 판매자의 최종 수취 금액이며, 현지 통화 기준의 원래 청구 총액과 자동으로 같아지는 값이 아닙니다. 두 숫자의 단위가 같은 것처럼 비교하지 마세요. 서버에서 처음 승인한 주문과 가격 산정 맥락을 보관하세요.
동적 구매에는 API Checkout 흐름을 사용해 주문과 세션의 연결을 유지하세요. 고정 상품에는 결제 링크가 재사용 가능한 결제 진입점을 제공합니다. 이행 여부는 여전히 애플리케이션이 결정해야 합니다.
이벤트 테이블뿐 아니라 실제 업무 효과도 보호하기
주문 이행이 전적으로 데이터베이스 안에서 이루어진다면 이벤트 처리 결과와 주문 상태 변경을 하나의 트랜잭션에 기록하세요. 일회성 주문당 한 번의 이용 권한 부여처럼 업무 작업의 고유성을 강제해야 합니다. 중복 이벤트는 기존 결과를 반환해야 하며 권한을 한 번 더 부여해서는 안 됩니다.
이행 과정에서 다른 서비스를 호출한다면 영구 발신함을 사용하세요. 실행할 작업을 주문 상태 변경과 함께 저장한 뒤 작업 프로세스가 전달하도록 합니다. 수신 서비스가 지원한다면 후속 작업에 주문 기준의 안정적인 멱등성 키를 부여하세요. 원격 작업이 성공한 직후 작업 프로세스가 중단되면 발신함만으로는 원격 중복 실행을 막을 수 없습니다.
대상 서비스가 멱등성도 결과 조회도 지원하지 않는다면 되돌릴 수 없는 작업을 무작정 재시도하지 말고, 불확실한 결과를 대사 대상으로 남겨두세요. HTTP Webhook이 모든 데이터베이스, 큐, 외부 서비스에 걸쳐 “정확히 한 번”을 보장할 수는 없습니다.
오래된 이벤트가 완료된 주문을 이전 상태로 되돌리지 못하게 하세요. invoice.overdue는 한 번의 결제 시도에 관한 이벤트이므로 이미 이행한 주문의 사실을 지워서는 안 됩니다. 정기 이용 권한의 경우 제공업체는 청구서 이벤트와 subscription.overdue, subscription.cancelled를 구분합니다. 문서에 명시된 구독 정책은 별도로 구현하세요.
실제 주문을 받기 전에 실패 경로 테스트하기
수신기와 작업 프로세스에 다음 인수 테스트를 적용하세요.
- 동일한 서명 이벤트를 두 번 전달하고 동시 전달도 시험합니다. 저장 이벤트 하나, 업무 효과 한 번만 발생해야 합니다.
- 주문 상태 변경 전후에 작업 프로세스를 중단합니다. 복구 과정에서 이용 권한이 두 번 부여되어서는 안 됩니다.
- 한 주문에 대해 확인된 결제 시도를 두 건 전달합니다. 한 번만 이행하고 추가 입금을 표시해야 합니다.
- 잘못된 서명, 조직 불일치, 알 수 없는 주문을 보냅니다. 어떤 경우에도 이행해서는 안 됩니다.
- 결제 확인 후 더 오래된 청구서 이벤트를 전달합니다. 완료된 이행이 취소되어서는 안 됩니다.
- 테스트 모드 이벤트를 운영 수신기에 보냅니다. 실제 라이선스 발급, 배송, 계정 잔액 적립이 발생해서는 안 됩니다.
Yolfi 관리 화면의 테스트 이벤트는 livemode: false와 evt_test_로 시작하는 ID를 사용합니다. 전달과 페이로드 처리를 시험하지만 실제 결제 레코드는 생성하지 않습니다. 테스트 효과와 실제 효과를 명시적으로 분리하세요. 테스트 알림이 성공했다고 해서 구매 대금이 정산되었다는 증거가 되지는 않습니다.
인증 후 처리를 기다리는 이벤트, 작업 프로세스 오류, 결제는 확인되었지만 이행 결과가 없는 건을 모니터링하세요. 이런 예외를 결제 대사 점검표와 연결하세요. 두 번째 입금이 재시도가 아니라 실제 추가 결제라면 증거를 삭제하지 말고 환불 검토 절차를 따르세요.
자주 묻는 질문
서명 검증으로 중복 적립을 막을 수 있나요?
아니요. 서명은 진위와 무결성을 검증합니다. 진짜 이벤트도 여러 번 도착할 수 있고, 과거에 유효했던 요청이 재전송될 수도 있습니다. 이벤트 ID를 영구 저장하고 주문 단위의 업무 제약을 적용하세요.
이벤트를 저장하기 전에 성공 응답을 보내야 하나요?
아니요. 영구 저장한 뒤 수신을 확인하고, 오래 걸리는 작업은 비동기로 수행하세요. 그렇지 않으면 응답 후 발생한 장애로 이벤트가 아무런 표시 없이 사라질 수 있습니다.
트랜잭션 해시만으로 중복 제거 키가 충분한가요?
Webhook 처리에는 충분하지 않습니다. 이벤트 전달에는 문서에 명시된 서명된 이벤트 ID를, 주문 이행에는 자체 주문 키를 사용하세요. 송금과 주문은 서로 다른 식별 대상을 가지며, 하나의 트랜잭션에 여러 송금이 포함될 수 있습니다.
어댑터 페이로드에도 같은 처리기를 쓸 수 있나요?
인터페이스 규약을 확인하지 않고 재사용해서는 안 됩니다. 이 글은 어댑터가 NONE인 기본 형식을 설명합니다. 제공업체 호환 어댑터는 페이로드 구조가 다를 수 있으므로 기본 파싱 및 연결 규칙을 재사용하기 전에 해당 문서의 필드를 검증하세요.
결론: 확인하고 저장한 뒤 한 번만 이행하기
안정적인 암호화폐 결제 자동화는 인증된 이벤트 전달과 주문의 업무 효과를 분리합니다. 원본 서명을 검증하고, 이벤트를 영구 저장하고, 주문을 연결하고, 재시도해도 안전하게 이행되도록 만드세요. 고정 상품은 Yolfi 결제 링크로 시작하고 동적 주문은 문서에 설명된 서버 생성 세션을 사용하되, 각 구매를 한 번만 제공할 책임은 애플리케이션에 두세요.
