주의 사항
SoloPay를 연동할 때 반드시 알아야 할 핵심 사항을 정리합니다.
orderId는 왜 필요한가요?
orderId는 가맹점 내 중복 결제를 방지하는 멱등성(idempotency) 키입니다.- 같은
orderId로 재요청하면DUPLICATE_ORDER(409) 에러가 반환됩니다. - 주문 1건 =
orderId1개 원칙을 지켜야 합니다.
사용자가 결제 중간에 창을 닫으면?
successUrl/failUrl은 브라우저 리다이렉트에 의존하므로, 유저가 창을 닫으면 도달하지 못합니다.- 반드시 Webhook(
payment.paid,payment.invalid)을 구현해야 안정적으로 결제 결과를 수신할 수 있습니다. - Webhook + Callback URL 병행 사용을 권장합니다.
- Fallback 수단으로
GET /merchant/payments/:id폴링을 활용할 수 있습니다.
결제 결과를 반드시 서버에서 검증하세요
- URL 쿼리 파라미터(
paymentId,status)는 사용자가 조작할 수 있습니다. - 반드시 서버에서
GET /merchant/payments/:id를 호출하여 실제 결제 상태를 확인해야 합니다. - 검증 체크리스트:
status가PAID인지 확인 (결제 성공)amount가 자사 주문 DB에 저장된 기대 금액과 일치 확인 (위젯은 클라이언트에서 실행되므로 금액이 변조될 수 있음)tokenAddress가 기대한 토큰 컨트랙트 주소와 일치 확인orderId가 일치하는지 확인- 동일
paymentId중복 처리 방지
직접 결제 모델
- SoloPay는 자금이 온체인에서 가맹점 지갑으로 직접 전송되는 직접 결제 모델을 사용합니다.
- 에스크로 단계가 없으며, 결제가 PAID로 확인되면 가맹점이 자금을 수령한 것입니다.
- 필요한 경우, 가맹점은 POST /refunds를 통해 환불을 요청할 수 있습니다 (PAID 상태 필요).
PAID 상태 수신 시 무엇을 검증해야 하나요?
payment.paid웹훅 수신을 확인하거나,GET /merchant/payments/:id로status === "PAID"를 확인합니다.amount가 자사 주문 DB에 저장된 기대 금액과 일치하는지 확인합니다 — 위젯은 클라이언트에서 실행되므로 결제 요청의 금액이 변조되었을 수 있습니다.orderId와tokenAddress를 주문 데이터와 대조합니다.- 해당 결제가 이미 처리되지 않았는지 확인합니다 (주문 중복 완료 방지).
환불은 어떻게 하나요?
현재 SoloPay는 자동화된 환불 기능을 제공하지 않습니다. 환불이 필요한 경우 가맹점에서 직접 처리해야 합니다.
환불은 가맹점이 직접 처리해야 합니다
SoloPay는 직접 결제 모델로 동작하며, 결제 즉시 자금이 가맹점 지갑으로 전송됩니다. 환불이 필요한 경우 가맹점이 구매자에게 직접 송금하거나, 자체 환불 정책에 따라 처리해야 합니다.