rollback — 출금 취소
앞서 보낸 debit 하나를 취소하고 그 금액을 플레이어에게 돌려줍니다. 플랫폼은 rollback 을 OK 를 받을 때까지 재시도합니다. 원 debit 이 오퍼레이터에 도착하지 않았을 수도 있으므로, 그 경우까지 처리해야 합니다.
http
POST {wallet_base_url}/rollback언제 호출되나
reason | 언제 | 원 debit 이 오퍼레이터에 있나 |
|---|---|---|
cancel_bet | 플레이어가 베팅 마감 전에 베팅을 취소 | 있음 (OK 를 받은 debit) |
round_void | 라운드가 무효가 됨 (게임 진행 오류, 플랫폼 서버 복구 등). 그 라운드에서 정산되지 않은 debit 마다 한 건씩 | 대개 있음. 결과가 불확실했던 debit 이면 없을 수 있음 |
timeout | debit 결과가 불확실함 (3초 타임아웃, HTTP 200 아님, 연결 실패, UNKNOWN_ERROR). debit 실패 직후 바로 보냄 | 모름 — 도착하지 않았거나, 늦게 처리됐거나, 아직 처리 중일 수 있음 |
system | 플랫폼 서버가 debit 도중 멈춰 30초 넘게 결과를 모르는 debit 을 정리, 서버 복구 때 착석 도중 멈춘 바이인을 정리 | 모름 |
- rollback 은 debit 만 취소합니다. credit 은 취소하지 않습니다.
- 한 debit 에 대한 rollback 의
tx_id는 하나로 정해져 있습니다. 같은 debit 을 사유를 바꿔 두 번 취소하지 않습니다. - 새로운
reason값이 추가될 수 있습니다. 모르는 값이 와도 거절하지 마세요.
요청
헤더는 공통 헤더와 같습니다.
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
tx_id | string | ● | rollback 거래 자체의 ID. 멱등 키 |
ref_tx_id | string | ● | 취소할 debit 의 tx_id |
external_id | string | ● | 오퍼레이터 쪽 플레이어 ID |
player_id | string | ● | 플랫폼 플레이어 ID(pl_…), 참고용 |
currency | string | ● | 통화 코드 |
amount | integer | ● | 원 debit 의 금액 (1 이상). 일부만 취소하는 rollback 은 없습니다 |
reason | string | ● | 위 표의 값 |
game_code | string | ● | 게임 코드. 플랫폼 복구 경로에서는 빈 문자열일 수 있음 |
table_id | string | ● | 테이블 ID (tbl_…) |
round_id | string | ● | 원 debit 의 라운드 ID(rnd_…) 또는 테이블 세션 ID(tss_…) |
operator_session_id | string | null | ● | 게임 실행 때 보낸 값. 플랫폼 복구 경로(system · round_void)에서는 null 일 수 있음 |
created_at | string | ● | 플랫폼이 rollback 거래를 만든 시각 (UTC, 밀리초). 재시도해도 바뀌지 않음 |
json
{
"amount": 5000,
"created_at": "2026-10-19T02:10:03.131Z",
"currency": "PHP",
"external_id": "u-102938",
"game_code": "live_baccarat",
"operator_session_id": "s-88af21",
"player_id": "pl_0199e8b4f2a37c1d8e5b6a4f3c2d1e0b",
"reason": "timeout",
"ref_tx_id": "tx_0199f2a1c3d47e8b9a6f1e2d3c4b5a69",
"round_id": "rnd_0199f2a0b1c27d3e8f4a5b6c7d8e9f01",
"table_id": "tbl_0199a1b2c3d47e5f8a9b0c1d2e3f4a5b",
"tx_id": "tx_3b7e1c9a5d2f4e8b6a0c2d4f6e8a0b1c"
}json
{
"amount": 5000,
"created_at": "2026-10-19T02:10:09.870Z",
"currency": "PHP",
"external_id": "u-102938",
"game_code": "live_baccarat",
"operator_session_id": "s-88af21",
"player_id": "pl_0199e8b4f2a37c1d8e5b6a4f3c2d1e0b",
"reason": "cancel_bet",
"ref_tx_id": "tx_0199f2a1c3d47e8b9a6f1e2d3c4b5a70",
"round_id": "rnd_0199f2a0b1c27d3e8f4a5b6c7d8e9f01",
"table_id": "tbl_0199a1b2c3d47e5f8a9b0c1d2e3f4a5b",
"tx_id": "tx_9d1f3a5c7e9b0d2f4a6c8e0b2d4f6a8c"
}응답
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
status | string | ● | OK 여야 끝납니다 |
balance | integer | ● | 처리 후 잔액 |
operator_tx_id | string | 오퍼레이터 쪽 거래 ID |
json
{ "status": "OK", "balance": 1250000, "operator_tx_id": "w-99814" }경우별 처리
ref_tx_id 의 debit 상태에 따라 처리가 다릅니다. 모든 경우에 OK 를 돌려줍니다.
| 원 debit 상태 (오퍼레이터 기록) | 처리 | 응답 |
|---|---|---|
| 성공(차감됨) | 원 debit 금액을 환원하고 debit 을 "롤백됨"으로 표시 | OK + 환원 후 잔액 |
| 기록 없음 (도착하지 않았거나 아직 처리 전) | 환원하지 않고 ref_tx_id 를 롤백 표시에 기록 | OK + 현재 잔액 |
거절했던 debit (INSUFFICIENT_FUNDS 등) | 환원하지 않음, 롤백 표시에 기록 | OK + 현재 잔액 |
| 이미 롤백됨 | 아무것도 하지 않음 | OK + 현재 잔액 |
같은 rollback tx_id 재요청 | 다시 처리하지 않음 | 처음 응답 그대로 |
- 환원 금액은 오퍼레이터가 기록한 원 debit 금액을 쓰세요. 요청의
amount는 같은 값이지만, 원 기록과 다르면 원 기록이 기준입니다. - 플레이어가 차단 · 로그아웃 · 세션 만료 상태여도 환원합니다.
원 debit 이 아직 없을 때
timeout · system rollback 은 원 debit 보다 먼저 처리될 수 있습니다. 예를 들어 오퍼레이터가 debit 을 3초 넘게 처리하는 동안 플랫폼은 이미 실패로 보고 rollback 을 보냅니다.
플랫폼 오퍼레이터
debit tx_10 (5,000) ─────────────────▶ 처리 지연 …
── 3초 경과, 베팅 거절 ──
rollback tx_11 (ref=tx_10) ─────────▶ tx_10 기록 없음 → 환원 없이 OK, tx_10 롤백 표시
(늦게 이어진 debit tx_10 처리)
tx_10 이 롤백 표시에 있음 → TX_ALREADY_ROLLED_BACK, 차감 안 함반대로 debit 이 먼저 커밋되고 rollback 이 뒤에 오면 "성공 → 환원" 경우가 됩니다. 어느 쪽이든 최종 잔액은 debit 이 없었던 것과 같아야 합니다.
이를 지키려면:
- debit · rollback 을 같은 플레이어 행 잠금 안에서 처리합니다.
- debit 은 잠금을 잡은 뒤에 롤백 표시를 확인합니다. 잠금 전에 확인하면, rollback 이 그 사이에 커밋됐을 때 debit 이 롤백 표시를 놓치고 차감해 버립니다.
- 롤백 표시는 지우지 않습니다(적어도 며칠은 보관). 늦은 debit 은 보통 몇 초 안에 오지만 오퍼레이터 쪽 장애로 더 늦을 수 있습니다.
rollback 은 거절할 수 없습니다
rollback 에 OK 가 아닌 응답(TX_ALREADY_ROLLED_BACK, PLAYER_NOT_FOUND 포함)을 주면 그 거래는 끝나지 않고 1초 → 2초 → 5초 → 15초 → 1분 → 5분, 이후 5분마다 기한 없이 재시도됩니다. 원 debit 을 찾지 못해도, 이미 롤백했어도 OK 를 돌려주세요.
처리 순서
- 서명 검증 → 실패면
INVALID_SIGNATURE(재시도되므로 원인을 바로 고쳐야 합니다) - 필드 검증(
tx_id·ref_tx_id·external_id존재,amount가 1 이상의 정수) → 실패면INVALID_REQUEST - 같은 rollback
tx_id기록이 있으면 → 저장된 응답을 그대로 반환 - 플레이어 행 잠금
ref_tx_id의 debit 조회(잠금) → 위 경우별 처리- 롤백 표시 기록, rollback
tx_id와 응답 기록,OK반환