구독/결제 비즈니스 로직의 일관성을 검증합니다. 월간 사용량 한도, 추천인 코드 적용, PortOne 웹훅 검증. subscription.py 또는 portone_service.py 수정 후 사용.
구독 및 결제 시스템의 비즈니스 규칙 일관성을 검사합니다:
backend/app/routers/subscription.py 수정 후backend/app/services/portone_service.py 수정 후backend/app/services/referral_service.py 수정 후| File |
|---|
| Purpose |
|---|
backend/app/routers/subscription.py | /api/subscription/activate 엔드포인트, 웹훅 라우터 |
backend/app/services/portone_service.py | PortOne API 연동, 빌링키 결제, 웹훅 처리 |
backend/app/services/subscription_service.py | 구독 상태 조회/업데이트, monthly_usage |
backend/app/services/referral_service.py | 추천인 코드 검증/적용/할인 |
frontend/src/components/PaymentButton.tsx | IFRAME 방식 결제 (referralCode 전달) |
frontend/src/app/subscription/callback/page.tsx | REDIRECTION 방식 콜백 (referral_code 전달) |
파일: backend/app/services/subscription_service.py, backend/app/routers/subscription.py
검사: 월간 사용량 체크 로직이 존재하고 tier별로 올바른 한도를 적용하는지 확인합니다.
grep -n "monthly_usage\|usage_limit\|max_usage\|quota" backend/app/services/subscription_service.py | head -20
grep -n "monthly_usage\|get_monthly_usage\|usage" backend/app/routers/subscription.py | head -10
PASS: get_monthly_usage()가 tier별 한도를 올바르게 반환하고, 영상 생성 전 한도 초과 체크 FAIL: 한도 체크 없이 무제한 생성 허용, 또는 basic/premium 구분 없이 동일한 한도 적용
파일: 프론트엔드 결제 파일들, backend/app/routers/subscription.py
검사: IFRAME 방식(PaymentButton)과 REDIRECTION 방식(callback page) 모두에서 referral_code가 백엔드에 전달되는지 확인합니다.
grep -n "referralCode\|referral_code" frontend/src/components/PaymentButton.tsx
grep -n "referralCode\|referral_code" frontend/src/app/subscription/callback/page.tsx
grep -n "referral_code\|referral_validated\|apply_code" backend/app/routers/subscription.py | head -15
PASS: PaymentButton.tsx와 callback/page.tsx 모두 referral_code를 백엔드에 전달, subscription.py에서 apply_code() 호출 FAIL: 한쪽 경로에서만 전달, 또는 키 이름 불일치 (referralCode vs referral_code)
파일: backend/app/routers/subscription.py
검사: /api/webhook/portone 엔드포인트에서 웹훅 서명 또는 토큰 검증이 있는지 확인합니다.
grep -n "webhook\|signature\|portone_webhook\|verify" backend/app/routers/subscription.py | head -15
grep -n "webhook_secret\|WEBHOOK\|verify_webhook" backend/app/services/portone_service.py | head -10
PASS: 웹훅 처리 시 서명 검증 또는 payment_id 재조회 검증 존재 WARN: 서명 검증 없이 웹훅 데이터 그대로 신뢰 — 위변조 가능성 (보안 위험)
파일: backend/app/routers/subscription.py
검사: 코드에 하드코딩된 가격이 설계 문서와 일치하는지 확인합니다.
grep -n "39000\|59000\|tier_price\|base_price\|price" backend/app/routers/subscription.py | head -15
기준 가격 (현재 코드 기준):
PASS: 위 가격이 코드에 존재하고 일관되게 사용됨 FAIL: 가격 불일치 또는 하드코딩 없이 환경변수 미설정으로 0원 처리
파일: backend/app/routers/subscription.py
검사: VALID_TIERS 집합이 프론트엔드에서 사용하는 planType 값과 일치하는지 확인합니다.
grep -n "VALID_TIERS\|valid_tiers" backend/app/routers/subscription.py
grep -n "planType\|plan_type\|basic\|premium" frontend/src/components/PaymentButton.tsx | head -10
PASS: VALID_TIERS = {"basic", "premium"}이고 프론트에서도 "basic"/"premium"만 전달 FAIL: 프론트에서 "standard", "pro" 등 다른 값 전달 — 422 validation error
### verify-subscription 결과
| 검사 | 상태 | 상세 |
|------|------|------|
| 월간 사용량 한도 로직 | PASS/FAIL | tier별 한도 체크 존재 |
| 추천인 코드 두 경로 전달 | PASS/FAIL | IFRAME + REDIRECTION 모두 |
| 웹훅 서명 검증 | PASS/WARN | 검증 존재 여부 |
| tier 가격 일관성 | PASS/FAIL | 39000/59000 코드 일치 |
| VALID_TIERS 일관성 | PASS/FAIL | 프론트/백엔드 tier 값 |
다음은 위반이 아닙니다:
...(referralCode ? {...} : {}))이면 PASS