Skip to content

[Feature] (판매자) 계좌인증 API#579

Merged
kimbro97 merged 6 commits intodevfrom
feature/account-verification
Feb 2, 2026
Merged

[Feature] (판매자) 계좌인증 API#579
kimbro97 merged 6 commits intodevfrom
feature/account-verification

Conversation

@kimbro97
Copy link
Contributor

@kimbro97 kimbro97 commented Jan 31, 2026

Reviewer

1팀

History

🚀 Major Changes & Explanations

  • (판매자) 계좌정보 인증

  • 기존 은행 이름 방식에서 은행 코드 방식으로 변경 (API 연동 표준화 및 정확성 향상)

  • 계좌번호는 AES-256 양방향 암호화하여 DB에 저장 (정산 등 필요 시 복호화하여 사용)

Summary by CodeRabbit

  • 새로운 기능

    • 판매자 계좌 검증 엔드포인트 추가 및 외부 계좌조회 연동 포인트 도입
    • AES 암호화 유틸리티 및 암호화/복호화 오류 코드 추가
  • 개선사항

    • 요청 필드 표준화: 은행명→은행코드(bankCode)로 변경 및 생성 팩토리 도입
    • 검증 결과를 반환하는 응답 포맷 강화
  • 테스트

    • 계좌 검증 및 암호화 유틸 관련 단·통합 테스트 추가
  • DB 마이그레이션

    • 계좌 테이블 컬럼명 변경 마이그레이션 추가

✏️ Tip: You can customize this high-level summary in your review settings.

- AccountVerification 엔티티 bankName → bankCode 필드명 변경
- 계좌번호 양방향 암호화 유틸리티(AesEncryptionUtil) 추가
- 암호화 관련 에러코드 추가 (ENCRYPTION_FAILED, DECRYPTION_FAILED)
- Flyway 마이그레이션 V32 추가 (bank_name → bank_code)
- 환경변수 설정 추가 (encryption.aes.secret-key)
- 도메인 단위 테스트 추가
- AccountVerificationClient 인터페이스 정의 (String 반환)
- TossAccountVerificationClient 구현체 추가 (현재 Fake 데이터 반환)
- AccountVerificationService에 verifyAccount 메서드 추가
- VerifyAccountCommand, AccountVerificationInfo DTO 추가
- 서비스 단위 테스트 및 통합 테스트 추가
- POST /api/v1/seller/sellers/account-verifications 엔드포인트 추가
- AccountVerificationRequest DTO 추가
- Controller에서 Info 객체 직접 반환 (Response DTO 미사용)
- Swagger 문서 작성 (@operation, @apiresponse)
@kimbro97 kimbro97 requested a review from kmindev January 31, 2026 16:25
@kimbro97 kimbro97 self-assigned this Jan 31, 2026
@kimbro97 kimbro97 added the feat New feature or request label Jan 31, 2026
@coderabbitai
Copy link

coderabbitai bot commented Jan 31, 2026

Walkthrough

판매자 계좌 인증 흐름(엔드포인트·서비스·외부 클라이언트), 계좌번호 AES-GCM 암호화 유틸리티, 관련 에러 코드(ENCRYPTION_FAILED/DECRYPTION_FAILED), DB 마이그레이션 및 관련 단위·통합 테스트를 추가/수정했습니다.

Changes

Cohort / File(s) Summary
에러 코드
src/main/java/com/bbangle/bbangle/exception/BbangleErrorCode.java
ENCRYPTION_FAILED, DECRYPTION_FAILED enum 상수 추가 (HttpStatus.INTERNAL_SERVER_ERROR).
도메인 변경 + DB 마이그레이션
src/main/java/com/bbangle/bbangle/seller/domain/AccountVerification.java, src/main/resources/flyway/V32__app.sql
필드 bankNamebankCode로 변경, 생성자 접근제어를 private로 변경하고 create static factory 추가; DB 컬럼명 bank_namebank_code로 변경하는 마이그레이션 추가.
컨트롤러 / API 정의 / DTO
src/main/java/com/bbangle/bbangle/seller/seller/controller/SellerController.java, src/main/java/com/bbangle/bbangle/seller/seller/controller/swagger/SellerApi.java, src/main/java/com/bbangle/bbangle/seller/seller/controller/dto/SellerRequest.java
POST /account-verifications 엔드포인트 추가 및 서명 변경, Swagger 문서/예시 업데이트, AccountVerificationRequest 레코드 및 toCommand 추가.
서비스 계층 및 커맨드/응답 DTO
src/main/java/com/bbangle/bbangle/seller/seller/service/AccountVerificationService.java, src/main/java/com/bbangle/bbangle/seller/seller/service/command/VerifyAccountCommand.java, src/main/java/com/bbangle/bbangle/seller/seller/service/info/AccountVerificationInfo.java
verifyAccount(VerifyAccountCommand) 추가: 판매자 조회, 외부 검증 호출, 암호화(AES), AccountVerification 생성·저장 및 AccountVerificationInfo 반환; VerifyAccountCommand·AccountVerificationInfo 추가.
외부 클라이언트(인터페이스 + 구현)
src/main/java/com/bbangle/bbangle/seller/seller/service/client/AccountVerificationClient.java, src/main/java/com/bbangle/bbangle/seller/seller/service/client/TossAccountVerificationClient.java
AccountVerificationClient 인터페이스 추가 및 TossAccountVerificationClient 컴포넌트 구현(현재 플레이스홀더 응답).
암호화 유틸리티 및 설정
src/main/java/com/bbangle/bbangle/util/AesEncryptionUtil.java, src/main/resources/application-dev.yml, src/main/resources/application-local.yml, src/main/resources/application-production.yml, src/test/resources/application.yml
AES-GCM 기반 암호화/복호화 컴포넌트 추가(비밀키 주입 및 길이 검증). 설정 키 항목(encryption.aes.secret-key) 추가 및 테스트용 키 포함. 예외 발생 시 신규 에러 코드 사용.
테스트
src/test/java/com/bbangle/bbangle/seller/domain/AccountVerificationUnitTest.java, src/test/java/com/bbangle/bbangle/seller/seller/service/AccountVerificationServiceUnitTest.java, src/test/java/com/bbangle/bbangle/seller/seller/service/AccountVerificationServiceIntegrationTest.java, src/test/java/com/bbangle/bbangle/util/AesEncryptionUtilTest.java
엔티티/서비스 단위·통합 테스트와 암호화 유틸 테스트 추가: 성공/실패 경로, 암복호화 라운드트립, 키 유효성 검증 등.

Sequence Diagram

sequenceDiagram
    participant Client as Client
    participant Controller as SellerController
    participant Service as AccountVerificationService
    participant ExtClient as AccountVerificationClient
    participant Crypto as AesEncryptionUtil
    participant Repo as AccountVerificationRepository
    participant DB as Database

    Client->>Controller: POST /account-verifications (bankCode, accountNumber)
    Controller->>Service: verifyAccount(VerifyAccountCommand)
    Service->>Repo: findSellerById(sellerId)
    Repo-->>Service: Seller
    Service->>ExtClient: verifyAccount(bankCode, accountNumber)
    ExtClient-->>Service: accountHolder (nullable)
    Service->>Crypto: encrypt(accountNumber)
    Crypto-->>Service: encryptedAccountNumber
    Service->>Repo: save(AccountVerification(bankCode, encryptedAccountNumber, accountHolder, verified, seller))
    Repo->>DB: INSERT
    DB-->>Repo: OK
    Repo-->>Service: AccountVerification
    Service-->>Controller: AccountVerificationInfo
    Controller-->>Client: CommonResult<AccountVerificationInfo>
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~65 minutes

Possibly related PRs

Suggested labels

test

Suggested reviewers

  • kmindev
  • mono0801

Poem

🐰 풀밭에서 코드를 깎았네
은행코드 묻고, 토스에 손짓하고
숫자들은 암호 속에 포근히 눕고
테스트가 깔짝대며 불빛을 켜네
토끼가 기뻐 뛰며 박수 친다 🎉

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 5.88% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목이 주요 변경사항을 정확하게 반영합니다. '계좌인증 API'는 계좌 인증 기능 추가라는 핵심 변경을 명확하게 나타냅니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/account-verification

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In
`@src/main/java/com/bbangle/bbangle/seller/seller/service/client/TossAccountVerificationClient.java`:
- Around line 5-13: TossAccountVerificationClient.verifyAccount currently always
returns a fixed success value ("테스트예금주"), which is unsafe for production; update
it so the fake behavior is only used in non-production environments (e.g., check
active Spring profile or a feature flag) and otherwise fail-fast or delegate to
the real Toss API client; additionally add a warning log when the fake path is
taken so it's obvious in logs. Reference TossAccountVerificationClient and its
verifyAccount method and implement an environment/profile check (or annotate the
bean with `@Profile` for dev/test) and a clear logger message when returning the
fake value.

In `@src/main/java/com/bbangle/bbangle/util/AesEncryptionUtil.java`:
- Around line 16-56: AesEncryptionUtil currently derives a fixed IV from the key
(ivParameterSpec) which breaks security; change to authenticated AES-GCM with a
per-encryption random IV: update ALGORITHM to "AES/GCM/NoPadding", remove the
ivParameterSpec field and any use of new IvParameterSpec(keyBytes,..) in the
constructor (keep secretKeySpec creation but validate key length is 16/24/32
bytes), then in encrypt(String plainText) generate a fresh 12-byte IV with
SecureRandom for each call, create a GCMParameterSpec(128, iv) and init the
Cipher with secretKeySpec and that spec, encrypt and prepend (or otherwise
include) the IV to the ciphertext before Base64-encoding the combined bytes; in
decrypt(String encryptedText) Base64-decode, split out the IV (first 12 bytes),
create a GCMParameterSpec from it, init Cipher for DECRYPT_MODE with
secretKeySpec and that spec, and decrypt the remaining bytes; remove any code
that derives IVs from the key and ensure exceptions still map to
BbangleException as before.

In `@src/main/resources/flyway/V32__app.sql`:
- Around line 1-2: The current ALTER TABLE CHANGE COLUMN bank_name bank_code
risks data corruption and truncation; instead implement a safe multi-step
migration for account_verifications: add a new column bank_code VARCHAR(10),
populate it from bank_name using a deterministic mapping function/table or CASE
expressions (and explicitly handle/trim/validate values longer than 10 chars and
log unmapped names), verify row counts and integrity, then drop bank_name and
finally rename bank_code if desired; target the migration SQL that modifies
account_verifications and reference the bank_name → bank_code mapping logic so
the update uses that mapping before removing the old column.
🧹 Nitpick comments (3)
src/test/java/com/bbangle/bbangle/seller/domain/AccountVerificationUnitTest.java (1)

55-58: 두 번째 테스트의 assertion 보강을 권장합니다.

미인증 상태 테스트에서 isNotNull()isVerified() 외에 다른 필드 검증이 누락되어 있습니다. 첫 번째 테스트와의 일관성을 위해 bankCode, accountNumber, accountHolder, seller 필드도 검증하면 회귀 버그를 더 잘 감지할 수 있습니다.

♻️ 추가 assertion 제안
         // assert
         assertThat(accountVerification).isNotNull();
         assertThat(accountVerification.isVerified()).isFalse();
+        assertThat(accountVerification.getBankCode()).isEqualTo(bankCode);
+        assertThat(accountVerification.getAccountNumber()).isEqualTo(encryptedAccountNumber);
+        assertThat(accountVerification.getAccountHolder()).isEqualTo(accountHolder);
+        assertThat(accountVerification.getSeller()).isEqualTo(seller);
     }
src/main/java/com/bbangle/bbangle/seller/seller/controller/dto/SellerRequest.java (1)

26-28: 계좌번호 형식 유효성 검사 추가를 권장합니다.

현재 @NotBlank만 적용되어 있어 임의의 문자열이 허용됩니다. 계좌번호는 일반적으로 숫자로만 구성되고 길이 제한이 있으므로, 패턴 검증을 추가하면 잘못된 입력을 조기에 차단할 수 있습니다.

♻️ 패턴 유효성 검사 추가 제안
         `@Schema`(description = "계좌번호", example = "123412341234")
         `@NotBlank`(message = "계좌번호는 필수입니다.")
+        `@Pattern`(regexp = "^[0-9]{8,14}$", message = "계좌번호는 8~14자리 숫자만 입력 가능합니다.")
         String accountNumber
src/test/java/com/bbangle/bbangle/seller/seller/service/AccountVerificationServiceIntegrationTest.java (1)

121-140: 테스트 프로파일이 이미 적용되어 있지만, 실제 API 구현 시 테스트 격리 보장이 필요합니다.

현재 TossAccountVerificationClient는 스텁 구현(@Component로 등록된 실제 빈 사용)을 반환하고 있으며, 테스트는 이미 @ActiveProfiles("test")로 테스트 프로파일을 사용 중입니다. 다만 코드의 TODO 주석("토스페이먼츠 API 연동 후 실제 구현 예정")에서 보듯이, 실제 API 호출로 변경되면 테스트가 불안정해질 수 있습니다.

테스트 프로파일 전용 AccountVerificationClient 구현 또는 @MockBean을 통해 외부 의존성을 명시적으로 분리하는 것이 권장됩니다.

Comment on lines +5 to +13
@Component
public class TossAccountVerificationClient implements AccountVerificationClient {

@Override
public String verifyAccount(String bankCode, String accountNumber) {
// TODO: 토스페이먼츠 API 연동 후 실제 구현 예정
// 현재는 Fake 예금주명 반환
return "테스트예금주";
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

프로덕션 배포 시 위험: Fake 구현체가 항상 성공을 반환합니다.

현재 구현은 실제 계좌 검증 없이 항상 고정된 예금주명을 반환합니다. 이 상태로 프로덕션에 배포되면 모든 계좌가 유효한 것으로 처리되어 보안 및 데이터 무결성 문제가 발생할 수 있습니다.

실제 API 연동 전까지 다음 중 하나를 고려해 주세요:

🛡️ 권장 조치 방안

방안 1: 프로파일 기반 제한

+import org.springframework.context.annotation.Profile;
+
+@Profile("!prod")
 `@Component`
 public class TossAccountVerificationClient implements AccountVerificationClient {

방안 2: 경고 로깅 추가

+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
 `@Component`
 public class TossAccountVerificationClient implements AccountVerificationClient {
 
     `@Override`
     public String verifyAccount(String bankCode, String accountNumber) {
+        log.warn("[FAKE] 계좌 인증 요청 - bankCode: {}, 실제 API 연동 필요", bankCode);
         // TODO: 토스페이먼츠 API 연동 후 실제 구현 예정
         return "테스트예금주";
     }
🤖 Prompt for AI Agents
In
`@src/main/java/com/bbangle/bbangle/seller/seller/service/client/TossAccountVerificationClient.java`
around lines 5 - 13, TossAccountVerificationClient.verifyAccount currently
always returns a fixed success value ("테스트예금주"), which is unsafe for production;
update it so the fake behavior is only used in non-production environments
(e.g., check active Spring profile or a feature flag) and otherwise fail-fast or
delegate to the real Toss API client; additionally add a warning log when the
fake path is taken so it's obvious in logs. Reference
TossAccountVerificationClient and its verifyAccount method and implement an
environment/profile check (or annotate the bean with `@Profile` for dev/test) and
a clear logger message when returning the fake value.

Comment on lines +1 to +2
-- account_verifications 테이블의 bank_name 컬럼을 bank_code로 변경
ALTER TABLE account_verifications CHANGE COLUMN bank_name bank_code VARCHAR(10);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

은행명→은행코드 전환 시 데이터 백필/변환 누락 위험
컬럼 이름만 변경하면 기존 bank_name 값이 그대로 bank_code로 해석되어 데이터 정합성이 깨질 수 있습니다. 또한 기존 값 길이가 10자를 초과하면 절단 위험이 있습니다. 매핑 백필 또는 안전한 단계적 마이그레이션을 고려해 주세요.

🔧 안전한 마이그레이션 방향 예시
-ALTER TABLE account_verifications CHANGE COLUMN bank_name bank_code VARCHAR(10);
+ALTER TABLE account_verifications ADD COLUMN bank_code VARCHAR(10);
+-- TODO: bank_name → bank_code 매핑으로 백필
+-- UPDATE account_verifications SET bank_code = CASE bank_name ... END;
+-- ALTER TABLE account_verifications DROP COLUMN bank_name;
🤖 Prompt for AI Agents
In `@src/main/resources/flyway/V32__app.sql` around lines 1 - 2, The current ALTER
TABLE CHANGE COLUMN bank_name bank_code risks data corruption and truncation;
instead implement a safe multi-step migration for account_verifications: add a
new column bank_code VARCHAR(10), populate it from bank_name using a
deterministic mapping function/table or CASE expressions (and explicitly
handle/trim/validate values longer than 10 chars and log unmapped names), verify
row counts and integrity, then drop bank_name and finally rename bank_code if
desired; target the migration SQL that modifies account_verifications and
reference the bank_name → bank_code mapping logic so the update uses that
mapping before removing the old column.

@coderabbitai
Copy link

coderabbitai bot commented Feb 1, 2026

Note

Docstrings generation - SUCCESS
Generated docstrings for this pull request at #580

coderabbitai bot added a commit that referenced this pull request Feb 1, 2026
Docstrings generation was requested by @kimbro97.

* #579 (comment)

The following files were modified:

* `src/main/java/com/bbangle/bbangle/seller/domain/AccountVerification.java`
* `src/main/java/com/bbangle/bbangle/seller/seller/controller/SellerController.java`
* `src/main/java/com/bbangle/bbangle/seller/seller/controller/dto/SellerRequest.java`
* `src/main/java/com/bbangle/bbangle/seller/seller/controller/swagger/SellerApi.java`
* `src/main/java/com/bbangle/bbangle/seller/seller/service/AccountVerificationService.java`
* `src/main/java/com/bbangle/bbangle/seller/seller/service/client/AccountVerificationClient.java`
* `src/main/java/com/bbangle/bbangle/seller/seller/service/client/TossAccountVerificationClient.java`
* `src/main/java/com/bbangle/bbangle/seller/seller/service/info/AccountVerificationInfo.java`
* `src/main/java/com/bbangle/bbangle/util/AesEncryptionUtil.java`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants