✨ 기능 설명
현재 코드는 결제 완료 시 Settlement.status='Pending'으로 row 생성만 하고, Succeed로 업데이트하는 로직이 코드 전체에 없음(grep 검증 완료). 결과적으로 GET /pending-amount, /sales/monthly, /yearly 등 모든 정산 통계가 영구히 Pending에 머무름. #479/#480에서 추가한 utils/payple-settlement.ts(파트너 인증 + 정산내역 조회 + 페이지네이션)를 활용해 정산 완료 동기화를 구현.
3개 에이전트(architect / critic / security) 교차 검증 후 도출된 최적안.
✨ 핵심 결정 사항 (확정)
- 방식 A 단독 — KST 08:00 인앱
node-cron (기존 src/stats/jobs/prompt-stat-snapshot.job.ts 패턴 재사용). webhook은 명세 미확정이라 분리
- APPROVAL만 처리, CANCEL은 skip + WARN 로그 (환불은 enum 확장과 함께 별도 이슈)
- 금액 검증 필수:
PCD_SETTLE_AMOUNT == Settlement.amount일 때만 Succeed. 불일치는 alert + skip (Discrepancy 분류)
- 멱등 가드:
where: { payment_id, status: 'Pending' } updateMany — affected=0이면 skip
- Redis 분산 락 (
payple:settlement:sync:lock, NX EX 600)으로 중복 실행 차단
- lastKey Redis 영속화 + 페이지당 ≥1.1초 sleep + 잡당 페이지 한도. rate-limit 미완료 시 다음 cron이 이어받기
- 로그 redactor 적용 (
redactPaypleLog 재사용 + PCD_PAYER_NAME 등 PII 필드 추가)
- Auth 캐시 보안 강화: TTL 25분 → 15분 단축 + cstId/custKey는 캐시에서 제외하고 매번 env에서 로드 (#479의 utils/payple-settlement.ts 보강)
✨ 개발 목록
동기화 잡 (src/settlements/jobs/settlement-sync.job.ts)
매칭/업데이트 로직
보안/로그
환경변수
검증
✨ 별도 이슈로 분리 (본 PR 범위 밖)
- 환불(
CANCEL) 흐름 + Status.Refunded enum 확장 + Refund 모델 검토
- 6개월 백필 스크립트 (31일 슬라이딩 윈도우)
- Payple Webhook 도입 (실시간 보강)
PAYPLE_CUST_KEY 분리 / AWS Secrets Manager 이전
✨ 기타 설명 / 질문
✨ 기능 설명
현재 코드는 결제 완료 시
Settlement.status='Pending'으로 row 생성만 하고,Succeed로 업데이트하는 로직이 코드 전체에 없음(grep 검증 완료). 결과적으로GET /pending-amount,/sales/monthly,/yearly등 모든 정산 통계가 영구히 Pending에 머무름. #479/#480에서 추가한utils/payple-settlement.ts(파트너 인증 + 정산내역 조회 + 페이지네이션)를 활용해 정산 완료 동기화를 구현.3개 에이전트(architect / critic / security) 교차 검증 후 도출된 최적안.
✨ 핵심 결정 사항 (확정)
node-cron(기존src/stats/jobs/prompt-stat-snapshot.job.ts패턴 재사용). webhook은 명세 미확정이라 분리PCD_SETTLE_AMOUNT == Settlement.amount일 때만 Succeed. 불일치는 alert + skip (Discrepancy분류)where: { payment_id, status: 'Pending' }updateMany — affected=0이면 skippayple:settlement:sync:lock, NX EX 600)으로 중복 실행 차단redactPaypleLog재사용 +PCD_PAYER_NAME등 PII 필드 추가)✨ 개발 목록
동기화 잡 (
src/settlements/jobs/settlement-sync.job.ts)node-cron으로 KST 08:00 트리거 (timezoneAsia/Seoul)src/index.ts에startSettlementSyncJob()부트스트랩SET NX EX 600)PCD_START_DATE = PCD_END_DATE로 호출PCD_HAS_MORE=true동안PCD_LASTKEY사용payple:settlement:sync:lastkey:{yyyyMMdd})에 영속화prisma.$transaction1건씩){ date, processed, updated, skipped, missing, cancel_skipped, discrepancy, failed }매칭/업데이트 로직
PCD_PAY_OID→Payment.pcd_pay_oidlookupmissing카운트 + WARNtxnType === 'CANCEL'→cancel_skipped카운트 + WARN (본 PR 범위 밖)txnType === 'APPROVAL'처리:Settlement.payment_id조회 → 없으면missingPCD_SETTLE_AMOUNT === Settlement.amount검증 → 불일치 시discrepancy+ ERROR 로그 (자동 업데이트 금지)prisma.settlement.updateMany({ where: { payment_id, status: 'Pending' }, data: { status: 'Succeed' } })updated, 0 →skipped보안/로그
utils/payple-settlement.tsAuth 캐시 보강:AUTH_CACHE_TTL_SECONDS를 25분 → 15분으로 단축cstId/custKey제거 → 매 호출 시 env에서 직접 로드redactPaypleLog를 settlement util import → 요청/응답 로그 마스킹REDACTED_FIELDS에PCD_PAYER_NAME,PCD_PAY_OID등 추가 검토환경변수
PAYPLE_SETTLEMENT_SYNC_ENABLED(기본값true, dev 비활성화 가능)PAYPLE_SETTLEMENT_SYNC_MAX_PAGES_PER_RUN(기본 100)검증
pnpm build/pnpm tsc --noEmitcancel_skipped카운트 + 업데이트 안 됨 확인discrepancy카운트 + alert✨ 별도 이슈로 분리 (본 PR 범위 밖)
CANCEL) 흐름 +Status.Refundedenum 확장 +Refund모델 검토PAYPLE_CUST_KEY분리 / AWS Secrets Manager 이전✨ 기타 설명 / 질문
PCD_SETTLE_DATE확정 시각 이후인지 sandbox 검증 필요