TIL

78일차 TIL (토스 결제 구현 2일차)

ohs020105 2025. 3. 4. 21:04

오늘은 어제의 로직을 이어서 이번엔 실제로 결제는 안되지만 결제가 된다는 느낌을 가지는 테스트로 결제를 하게 된다면 다이아를 추가되는 로직을 추가했다.

 

우선 사진으로 보자면 

기본 아이템 상점에 다이아를 추가할 수 있게 추가했다.

 

구매하기 누르면 이렇게 자신의 상품내용하고 가격, 결제방법을 선택할 수 있다.

 

이렇게 각자 결제 방법에 맞게 입력을 해주고 다음으로 넘어가면 

 

이런식으로 충전이 완료되었다는 메세지 하고 

실제로 다이아가 추가가 된게 보인다.(사진찍겠다고 한번 넘어가버려서 다시 한번 더 한건 안비밀)

# TIL (Today I Learned) - Toss 결제 연동과 다이아 충전 구현

## 1. 구현 목표
- Toss Payments를 이용한 결제 시스템 구축
- 결제 완료 후 사용자의 다이아 수량 자동 업데이트
- 안전한 결제 처리와 사용자 인증 구현

## 2. 주요 구현 내용

### 2.1 결제 프로세스 구현
```typescript
// UserService에 다이아 충전 메서드 추가
async chargeDiamond(userId: number, amount: number) {
  try {
    const user = await this.userRepository.findId(userId);
    if (!user) {
      throw new NotFoundException('사용자를 찾을 수 없습니다.');
    }

    // 다이아 수량 업데이트
    const updateData: UpdateUserDto = {
      pink_dia: user.pink_dia + amount
    };
    await this.userRepository.updateUser(userId, updateData);

    // 캐시 업데이트
    const cacheKey = `user:${user.email}`;
    const cachedUser = await this.valkeyService.get<CachedUser>(cacheKey);
    if (cachedUser) {
      cachedUser.pink_dia = user.pink_dia + amount;
      await this.valkeyService.set(cacheKey, cachedUser, 60 * 60 * 12);
    }

    return {
      success: true,
      message: `${amount} 다이아가 충전되었습니다.`,
      currentDiamond: user.pink_dia + amount
    };
  } catch (error) {
    throw new InternalServerErrorException('다이아 충전 중 오류가 발생했습니다.');
  }
}
```

### 2.2 결제 완료 처리
```javascript
// success.html에서 결제 완료 후 처리
document.addEventListener('DOMContentLoaded', async () => {
  const accessToken = localStorage.getItem('accessToken');
  if (!accessToken) {
    alert('로그인이 필요합니다.');
    window.location.href = '/public/log-in.html';
    return;
  }

  try {
    if (urlParams.get('type') === 'diamond') {
      const itemName = urlParams.get('itemName');
      const diamondAmount = Number(itemName.replace(/[^0-9]/g, ''));

      const response = await fetch('/user/charge-diamond', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': `${accessToken}`
        },
        body: JSON.stringify({
          amount: diamondAmount,
          paymentKey: urlParams.get('paymentKey'),
          orderId: urlParams.get('orderId')
        })
      });
      // ... 결과 처리
    }
  } catch (error) {
    console.error('결제 처리 실패:', error);
  }
});
```

## 3. 주요 기술 포인트

### 3.1 사용자 인증
- LocalStorage에 저장된 accessToken을 활용한 사용자 인증
- API 요청 시 Authorization 헤더에 토큰 포함

### 3.2 데이터 동기화
- DB 업데이트와 캐시(Valkey) 동시 업데이트로 데이터 일관성 유지
- 트랜잭션 처리로 안전한 다이아 충전 구현

### 3.3 에러 처리
- 결제 실패, 인증 오류 등 다양한 예외 상황 처리
- 사용자에게 적절한 에러 메시지 표시

## 4. 개선사항
1. 결제 검증 로직 추가 필요
   - 실제 결제 금액과 상품 금액 일치 여부 확인
   - 중복 결제 방지 로직 구현

2. 보안 강화
   - 토큰 만료 처리
   - 결제 위변조 방지 로직 추가

3. 사용자 경험 개선
   - 결제 진행 상태 표시
   - 결제 실패 시 적절한 안내 메시지 제공

## 5. 학습 내용
1. Toss Payments API 연동 방법
2. 결제 프로세스 설계 및 구현
3. 캐시와 DB 동기화 처리
4. 사용자 인증 및 보안 처리
5. 프론트엔드와 백엔드 간의 데이터 흐름 관리

 

이제 할 건 앞으로 결제를 진행할때 취소를 누르면 다시 홈 화면이나 아님 마지막 화면(아이템상점)으로 돌아와야 되는데 아직 돌아가는 로직이 없다. 수정을 해야 될 것 같다.

 

따로 환불하는거나 아님 플러스할 서비스? 같은걸 추가해야 될 것 같다.

'TIL' 카테고리의 다른 글

80일차 TIL  (0) 2025.03.07
79일차 TIL (토스 구현 3일차)  (0) 2025.03.06
77일차 TIL  (0) 2025.03.03
76일차 TIL ( 면접 카타 9일차 )  (0) 2025.02.21
75일차 TIL ( 면접 카타 8일차 )  (0) 2025.02.20