diff --git a/app/api/payment/confirm/route.ts b/app/api/payment/confirm/route.ts index d0b5dcf..bcbe2b8 100644 --- a/app/api/payment/confirm/route.ts +++ b/app/api/payment/confirm/route.ts @@ -28,7 +28,14 @@ export async function POST(request: NextRequest) { } // 2. 토스페이먼츠 서버 승인 + // dev: TOSS_SECRET_KEY=test_sk_* (테스트 결제) + // prod: TOSS_SECRET_KEY=live_sk_* (실결제) — Vercel 환경변수에 설정 const secretKey = process.env.TOSS_SECRET_KEY!; + const isTestKey = secretKey.startsWith('test_'); + if (!isTestKey && process.env.NODE_ENV === 'development') { + // 실수로 live 키를 dev에서 쓰는 것 방지 + console.warn('[Payment] WARNING: live Toss key detected in development!'); + } const encoded = Buffer.from(`${secretKey}:`).toString('base64'); const tossRes = await fetch('https://api.tosspayments.com/v1/payments/confirm', { diff --git a/app/auth/callback/route.ts b/app/auth/callback/route.ts index 718a862..1d8195b 100644 --- a/app/auth/callback/route.ts +++ b/app/auth/callback/route.ts @@ -6,15 +6,15 @@ export async function GET(request: Request) { const code = searchParams.get('code'); const next = searchParams.get('next') ?? '/mypage'; - // 프로덕션 기준 URL 결정 - // 우선순위: NEXT_PUBLIC_SITE_URL > x-forwarded-host > origin + // 리다이렉트 기준 URL 결정 + // - dev: 항상 현재 request의 origin (localhost) → NEXT_PUBLIC_SITE_URL 무시 + // - prod: NEXT_PUBLIC_SITE_URL > x-forwarded-host (Vercel) > origin const siteUrl = process.env.NEXT_PUBLIC_SITE_URL; const forwardedHost = request.headers.get('x-forwarded-host'); - const baseUrl = - siteUrl ?? - (process.env.NODE_ENV !== 'development' && forwardedHost - ? `https://${forwardedHost}` - : origin); + const isDev = process.env.NODE_ENV === 'development'; + const baseUrl = isDev + ? origin + : (siteUrl ?? (forwardedHost ? `https://${forwardedHost}` : origin)); if (code) { const supabase = await createClient(); diff --git a/app/components/PaymentButton.tsx b/app/components/PaymentButton.tsx index ad7df11..e447a57 100644 --- a/app/components/PaymentButton.tsx +++ b/app/components/PaymentButton.tsx @@ -47,6 +47,8 @@ export default function PaymentButton({ productId, className, children, returnUr if (orderError) throw new Error('주문 생성 실패: ' + orderError.message); // 4. 토스페이먼츠 결제창 호출 + // dev: NEXT_PUBLIC_TOSS_CLIENT_KEY=test_ck_* → 테스트 결제 (실제 청구 없음) + // prod: NEXT_PUBLIC_TOSS_CLIENT_KEY=live_ck_* → 실결제 (Vercel 환경변수에 설정) const { loadTossPayments } = await import('@tosspayments/tosspayments-sdk'); const clientKey = process.env.NEXT_PUBLIC_TOSS_CLIENT_KEY!; const tossPayments = await loadTossPayments(clientKey); @@ -81,13 +83,29 @@ export default function PaymentButton({ productId, className, children, returnUr if (!product) return null; + const isTestMode = process.env.NEXT_PUBLIC_TOSS_CLIENT_KEY?.startsWith('test_'); + return ( - +