상태는 유니크하며, 이벤트가 발생하면 다른 상태로 변경된다.
1) 초기 상태도

보완)
결제 거부 , 환불 거부 이벤트가 일어날 때도 상태가 필요하므로 결제 취소 상태 와 환불 불가 상태를 추가하였다.
실제로 환불 되었으면 환불 영수증을 주고 다시 결제를 하므로, 상태도에서는 재결제 요청 보다는 새로운 결제 데이터가 쌓이도록 처리하였음
2) 최종 상태도

코드
@Override public Payment transit(Event event) { State nextState = (State) FSM.State.next(this.state, event); this.state = nextState; this.histories.add(new PaymentStateHistory(nextState, event, userId, series, this)); return this; } public enum State implements FSM.State<Event> { NULL(Set.of(Event.PAY_REQUIRED)), PAY_CONFIRMED(Set.of(Event.PAY_ACCEPTED, Event.PAY_REJECTED)), PAY_CANCELED(emptySet()), PAY_COMPLETE(Set.of(Event.REFUND_REQUIRED)), REFUND_CONFIRMED(Set.of(Event.REFUND_ACCEPTED, Event.REFUND_REJECTED)), REFUND_COMPLETE(emptySet()); final Set<Event> events; private State(Set<Event> events) { this.events = events; } @Override public Set<Event> getEvents() { return events; } } public enum Event implements FSM.Event<State> { PAY_REQUIRED { @Override public State getNextState() { return State.PAY_CONFIRMED; } }, PAY_ACCEPTED { @Override public State getNextState() { return State.PAY_COMPLETE; } }, PAY_REJECTED { @Override public State getNextState() { return State.PAY_CANCELED; } }, REFUND_REQUIRED { @Override public State getNextState() { return State.PAY_CONFIRMED; } }, REFUND_ACCEPTED { @Override public State getNextState() { return State.PAY_COMPLETE; } }, REFUND_REJECTED { @Override public State getNextState() { return State.PAY_CONFIRMED; } }; }
(+) 이벤트를 기록하는 기록용 테이블 추가 (payment_state_history)
유저는 언제 결제했고 언제 환불이 되었는지 확인 가능
1) 결제가 정상적으로 되었을 경우

2) 유저 포인트가 부족하여 결제가 취소 되었을 경우

통계적으로 재구매율과 환불 퍼센트, 만족 퍼센트 등을 뽑아낼 수도 있음
→ 추후 그래프 혹은 차트로 표현 가능