feat(backend): 업체 링크별 신청·구매 추적 API 추가

상품마다 업체에 단축 링크를 발급하고, 그 링크로 들어온 회원의 신청·구매를
업체별로 세기 위해서다. 아임웹은 주문 완료를 알려주지 않으므로 구매는
주문 API 를 주기적으로 훑어 찾는다.

- 아임웹 상품 동기화(imweb_products) — 회원 동기화와 같은 주기, 실패해도 회원 동기화는 계속
- 단축 링크 /r/{코드}: 사람의 클릭만 기록하고 클릭 ID(mg_ref)를 붙여 상품 페이지로 이동
  (이동 주소는 아임웹 사이트 안만 허용 — open redirect 방지)
- 회원 ↔ 클릭 연결(POST /api/partner-touches), 신청 기록에 클릭 ID 추가
- 마지막 클릭·30일 귀속, 결제완료 주문만 구매로 집계하고 환불·취소는 제외 (금액은 관리하지 않음)
- 관리자 API: 업체·링크 관리, 링크별 실적 상세, 구매 집계 새로고침
- 권한 요청에 product:read·order:read 추가, 토큰 권한 부족은 IMWEB_006
- 에러 코드 IMWEB_006, PARTNER_001~004 추가 및 클라이언트 사전 동기화

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-05 23:47:10 +09:00
parent 2f01bea6ef
commit 7bef853664
50 changed files with 3746 additions and 10 deletions
+6 -2
View File
@@ -28,8 +28,12 @@ async function bootstrap() {
// 글로벌 prefix — 모든 라우트가 /api/* 로 정규화됨 (Flutter, Web 양쪽 baseURL과 일치)
app.setGlobalPrefix('api', {
// 헬스체크 / 루트 상태 엔드포인트는 prefix 미적용
exclude: [{ path: '/', method: RequestMethod.GET }],
exclude: [
// 헬스체크 / 루트 상태 엔드포인트는 prefix 미적용
{ path: '/', method: RequestMethod.GET },
// 업체 단축 링크는 짧아야 하므로 /api 없이 /r/{코드} (PartnerRedirectController)
{ path: 'r/:code', method: RequestMethod.GET },
],
});
// 기본 주소('/') 접속 시 상태 확인용 텍스트 응답 추가