feat: 토스페이먼츠 결제 fade-out → 카카오 채널/문의하기로 전환

결제 방식 변경:
- ai-kit: PaymentButton 2개 → KAKAO_CHANNEL_URL 있으면 카카오버튼,
  없으면 ContactModal로 폴백. 가격(19,900원/월) 표시 유지
- prompt: PaymentButton → 카카오버튼 or openModal() 호출로 교체
  문의 시 샘플 파일 미리 제공 안내 유지
- saju: AI 해석 hasPaid=true 고정 → 무료 제공으로 전환
  사주 페이지 결제 버튼 → '무료로 사주 분석하기' 링크
  SajuAISection PaymentButton → 비활성화 주석 처리

환경변수 추가 (선택):
- NEXT_PUBLIC_KAKAO_CHANNEL_URL: 카카오 채널 채팅 링크
- NEXT_PUBLIC_TOSS_ME_URL: toss.me 개인 송금 링크
- 토스페이먼츠 PG 키 주석 처리 (재활성화 시 해제 가능)

사주 hero AI 패턴 제거:
- radial gradient orb 3개, blur 배경 → diagonal pattern
- 그래디언트 텍스트 → amber-400 단색

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-02 01:00:49 +09:00
parent 7c59dafaeb
commit 50872de773
5 changed files with 109 additions and 64 deletions

View File

@@ -2,7 +2,7 @@
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import Link from 'next/link'; import Link from 'next/link';
import PaymentButton from '../components/PaymentButton'; // PaymentButton 비활성화 — 토스페이먼츠 결제 일시 중단
import { createClient } from '@/lib/supabase/client'; import { createClient } from '@/lib/supabase/client';
const faqItems = [ const faqItems = [
@@ -77,22 +77,16 @@ export default function SajuPage() {
return ( return (
<div className="min-h-full bg-[#f0f5ff]"> <div className="min-h-full bg-[#f0f5ff]">
{/* ─── Hero ─── */} {/* ─── Hero ─── */}
<div className="relative overflow-hidden bg-gradient-to-br from-[#04102b] via-[#0a1f5c] to-[#04102b] px-6 py-14 lg:px-12"> <div className="relative overflow-hidden bg-[#04102b] px-6 py-14 lg:px-12" style={{ backgroundImage: 'repeating-linear-gradient(135deg, rgba(255,255,255,0.015) 0px, rgba(255,255,255,0.015) 1px, transparent 1px, transparent 40px)' }}>
<div className="absolute inset-0 opacity-[0.06]"
style={{ backgroundImage: 'radial-gradient(circle, #a78bfa 1px, transparent 1px)', backgroundSize: '30px 30px' }} />
<div className="absolute right-0 top-0 w-96 h-96 rounded-full bg-violet-500/10 blur-3xl -translate-y-1/2 translate-x-1/3" />
<div className="absolute left-1/3 bottom-0 w-64 h-64 rounded-full bg-amber-400/8 blur-3xl translate-y-1/2" />
<div className="relative max-w-3xl mx-auto text-center"> <div className="relative max-w-3xl mx-auto">
<div className="inline-flex items-center gap-2 bg-violet-400/10 border border-violet-400/25 text-violet-300 text-xs font-semibold px-4 py-1.5 rounded-full mb-5 tracking-wide"> <div className="flex items-center gap-2 mb-5">
<span className="w-1.5 h-1.5 rounded-full bg-amber-400 animate-pulse" /> <span className="w-1.5 h-1.5 rounded-full bg-amber-400 animate-pulse" />
× AI · <span className="text-violet-300/70 text-xs font-mono tracking-widest uppercase"> × AI · </span>
</div> </div>
<h1 className="text-4xl md:text-5xl font-extrabold text-white leading-tight mb-5 tracking-tight"> <h1 className="text-4xl md:text-5xl font-extrabold text-white leading-tight mb-5 tracking-tight">
AI가 <br /> AI가 <br />
<span className="text-transparent bg-clip-text bg-gradient-to-r from-[#c4b5fd] to-[#fbbf24]"> <span className="text-amber-400"></span>
</span>
</h1> </h1>
<p className="text-blue-200/70 text-base md:text-lg leading-relaxed mb-8 max-w-xl mx-auto"> <p className="text-blue-200/70 text-base md:text-lg leading-relaxed mb-8 max-w-xl mx-auto">
AI .<br /> AI .<br />
@@ -288,23 +282,14 @@ export default function SajuPage() {
))} ))}
</ul> </ul>
<div className="mt-6 pt-5 border-t border-white/10 relative"> <div className="mt-6 pt-5 border-t border-white/10 relative">
<div className="text-2xl font-extrabold text-amber-400">4,900</div> <div className="text-lg font-bold text-emerald-400 mb-1"> </div>
<div className="text-xs text-blue-300/70 mt-1 mb-4">1 · </div> <div className="text-xs text-blue-300/70 mt-1 mb-4"> · 12 AI </div>
{hasPaid ? (
<Link <Link
href="/saju/input" href="/saju/input"
className="block w-full text-center py-3 rounded-xl text-sm font-bold transition bg-amber-400 text-[#04102b] hover:bg-amber-300" className="block w-full text-center py-3 rounded-xl text-sm font-bold transition bg-amber-400 text-[#04102b] hover:bg-amber-300"
> >
</Link> </Link>
) : (
<PaymentButton
productId="saju_detail"
className="block w-full text-center py-3 rounded-xl text-sm font-bold transition bg-amber-400 text-[#04102b] hover:bg-amber-300"
>
AI
</PaymentButton>
)}
</div> </div>
</div> </div>
</div> </div>

View File

@@ -3,7 +3,7 @@
import { useState, useEffect, useRef } from 'react'; import { useState, useEffect, useRef } from 'react';
import ReactMarkdown from 'react-markdown'; import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm'; import remarkGfm from 'remark-gfm';
import PaymentButton from '@/app/components/PaymentButton'; // PaymentButton 비활성화 — 토스페이먼츠 결제 일시 중단, 무료 제공 중
interface BirthKey { interface BirthKey {
birth_year: number; birth_year: number;
@@ -313,13 +313,13 @@ export default function SajuAISection({
))} ))}
</div> </div>
<PaymentButton {/* 결제 일시 중단 — hasPaid=true이므로 이 분기는 표시되지 않음 */}
productId="saju_detail" <a
returnUrl={currentUrl} href={process.env.NEXT_PUBLIC_KAKAO_CHANNEL_URL ?? '/freelance?service=AI사주분석'}
className="inline-flex items-center gap-2 bg-gradient-to-r from-amber-500 to-amber-400 hover:from-amber-400 hover:to-amber-300 text-[#04102b] font-bold px-7 py-3 rounded-xl transition-all shadow-lg" className="inline-flex items-center gap-2 bg-amber-400 hover:bg-amber-300 text-[#04102b] font-bold px-7 py-3 rounded-xl transition-all"
> >
AI · 4,900 AI
</PaymentButton> </a>
</div> </div>
</div> </div>
); );

View File

@@ -76,7 +76,8 @@ export default async function SajuResultPage({ searchParams }: PageProps) {
const solarTermName = getSolarTermName(solarTermIndex); const solarTermName = getSolarTermName(solarTermIndex);
// ── 결제 여부 + 저장된 AI 해석 + 로또 구독 확인 ───────────────────── // ── 결제 여부 + 저장된 AI 해석 + 로또 구독 확인 ─────────────────────
let hasPaid = false; // 토스페이먼츠 결제 일시 중단 — AI 사주 해석 무료 제공 중
let hasPaid = true;
let savedInterpretation: string | null = null; let savedInterpretation: string | null = null;
let hasLottoSubscription = false; let hasLottoSubscription = false;
try { try {

View File

@@ -1,7 +1,17 @@
'use client'; 'use client';
import { useState } from 'react';
import Link from 'next/link'; import Link from 'next/link';
import PaymentButton from '../../components/PaymentButton'; import ContactModal from '../../components/ContactModal';
const KAKAO_CHANNEL_URL = process.env.NEXT_PUBLIC_KAKAO_CHANNEL_URL ?? null;
const AI_KIT_CHECKLIST = [
'주로 반복하는 업무 종류 (일지, 이메일, 보고서 등)',
'현재 주로 사용하는 AI 도구 (ChatGPT / Claude / Gemini 등)',
'하루 또는 주 단위로 같은 작업을 몇 번이나 반복하는지',
'사용 목적 (개인 효율화 / 팀 도입 / 소상공인 업무 등)',
];
/* ────────────────────────────────────────────────────────────── /* ──────────────────────────────────────────────────────────────
Before / After 데이터 — 각 도구별 실제 시간 비교 Before / After 데이터 — 각 도구별 실제 시간 비교
@@ -153,10 +163,20 @@ const FAQ = [
]; ];
export default function AiKitPage() { export default function AiKitPage() {
const totalMonthlySaving = 27; // 도구 합산 월 절약 시간(추정) const totalMonthlySaving = 27;
const [modalOpen, setModalOpen] = useState(false);
return ( return (
<div className="min-h-full bg-[#f0f4ff]"> <div className="min-h-full bg-[#f0f4ff]">
<ContactModal
isOpen={modalOpen}
onClose={() => setModalOpen(false)}
service="AI 자동화 키트 — 월 19,900원"
checklist={AI_KIT_CHECKLIST}
accentColor="text-indigo-400"
headerFrom="#0a0f2e"
headerTo="#0f1a5c"
/>
{/* ─── Hero ─── */} {/* ─── Hero ─── */}
<div className="relative overflow-hidden bg-[#0a0f2e] px-6 py-14 lg:px-12" style={{ backgroundImage: 'repeating-linear-gradient(135deg, rgba(255,255,255,0.015) 0px, rgba(255,255,255,0.015) 1px, transparent 1px, transparent 40px)' }}> <div className="relative overflow-hidden bg-[#0a0f2e] px-6 py-14 lg:px-12" style={{ backgroundImage: 'repeating-linear-gradient(135deg, rgba(255,255,255,0.015) 0px, rgba(255,255,255,0.015) 1px, transparent 1px, transparent 40px)' }}>
@@ -194,14 +214,30 @@ export default function AiKitPage() {
</div> </div>
<div className="flex flex-col gap-3"> <div className="flex flex-col gap-3">
<PaymentButton {KAKAO_CHANNEL_URL ? (
productId="ai_kit_monthly" <a
className="bg-blue-600 hover:bg-blue-500 text-white text-base font-bold px-8 py-4 rounded-xl transition-colors w-full max-w-xs" href={KAKAO_CHANNEL_URL}
returnUrl="/services/ai-kit" target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center justify-center gap-2 bg-[#FEE500] hover:bg-[#F5DC00] text-[#3A1D1D] text-base font-bold px-8 py-4 rounded-xl transition-colors w-full max-w-xs"
> >
{totalMonthlySaving} <svg viewBox="0 0 24 24" className="w-5 h-5" fill="currentColor"><path d="M12 3C6.477 3 2 6.477 2 10.5c0 2.438 1.418 4.6 3.584 5.977l-.916 3.41c-.086.32.283.573.56.38l4.014-2.674A11.29 11.29 0 0012 18c5.523 0 10-3.477 10-7.5S17.523 3 12 3z"/></svg>
</PaymentButton>
<p className="text-white/25 text-xs"> · </p> </a>
) : (
<button
onClick={() => setModalOpen(true)}
className="bg-blue-600 hover:bg-blue-500 text-white text-base font-bold px-8 py-4 rounded-xl transition-colors w-full max-w-xs"
>
{totalMonthlySaving}
</button>
)}
<button
onClick={() => setModalOpen(true)}
className="text-indigo-300/60 hover:text-indigo-300 text-sm underline underline-offset-2 transition-colors"
>
</button>
</div> </div>
</div> </div>
</div> </div>
@@ -475,14 +511,25 @@ export default function AiKitPage() {
<br /> . <br /> .
</p> </p>
<div className="flex flex-col items-center gap-3"> <div className="flex flex-col items-center gap-3">
<PaymentButton {KAKAO_CHANNEL_URL ? (
productId="ai_kit_monthly" <a
className="bg-gradient-to-r from-indigo-500 to-cyan-500 text-white text-base font-extrabold px-8 py-4 rounded-xl hover:opacity-90 hover:scale-[1.02] transition-all shadow-lg shadow-indigo-500/25 w-full max-w-sm" href={KAKAO_CHANNEL_URL}
returnUrl="/services/ai-kit" target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center justify-center gap-2 bg-[#FEE500] hover:bg-[#F5DC00] text-[#3A1D1D] text-base font-bold px-8 py-4 rounded-xl transition-colors w-full max-w-sm"
> >
{totalMonthlySaving} 19,900 <svg viewBox="0 0 24 24" className="w-5 h-5" fill="currentColor"><path d="M12 3C6.477 3 2 6.477 2 10.5c0 2.438 1.418 4.6 3.584 5.977l-.916 3.41c-.086.32.283.573.56.38l4.014-2.674A11.29 11.29 0 0012 18c5.523 0 10-3.477 10-7.5S17.523 3 12 3z"/></svg>
</PaymentButton> 19,900/
<p className="text-white/25 text-xs"> · · </p> </a>
) : (
<button
onClick={() => setModalOpen(true)}
className="bg-indigo-600 hover:bg-indigo-500 text-white text-base font-bold px-8 py-4 rounded-xl transition-colors w-full max-w-sm"
>
{totalMonthlySaving}
</button>
)}
<p className="text-white/25 text-xs"> · 19,900 · </p>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -3,7 +3,7 @@
import { useState } from 'react'; import { useState } from 'react';
import Link from 'next/link'; import Link from 'next/link';
import ContactModal from '../../components/ContactModal'; import ContactModal from '../../components/ContactModal';
import PaymentButton from '../../components/PaymentButton'; const KAKAO_CHANNEL_URL = process.env.NEXT_PUBLIC_KAKAO_CHANNEL_URL ?? null;
const CHECKLIST = [ const CHECKLIST = [
'주로 어떤 AI 도구를 사용하는지 (ChatGPT / Claude / Gemini)', '주로 어떤 AI 도구를 사용하는지 (ChatGPT / Claude / Gemini)',
@@ -472,16 +472,28 @@ export default function PromptPage() {
</div> </div>
{/* CTA */} {/* CTA */}
<div className="p-6"> <div className="p-6">
<PaymentButton {KAKAO_CHANNEL_URL ? (
productId={product.productId} <a
className="w-full py-3.5 rounded-xl text-sm font-extrabold transition-all hover:opacity-90 hover:scale-[1.01]" href={KAKAO_CHANNEL_URL}
style={{ background: product.accentColor, color: product.bgFrom }} target="_blank"
returnUrl="/services/prompt" rel="noopener noreferrer"
className="flex items-center justify-center gap-2 w-full py-3.5 rounded-xl text-sm font-extrabold transition-all hover:opacity-90"
style={{ background: '#FEE500', color: '#3A1D1D' }}
> >
<svg viewBox="0 0 24 24" className="w-4 h-4" fill="currentColor"><path d="M12 3C6.477 3 2 6.477 2 10.5c0 2.438 1.418 4.6 3.584 5.977l-.916 3.41c-.086.32.283.573.56.38l4.014-2.674A11.29 11.29 0 0012 18c5.523 0 10-3.477 10-7.5S17.523 3 12 3z"/></svg>
</PaymentButton>
</a>
) : (
<button
onClick={() => openModal(`프롬프트 패키지 — ${product.title}`)}
className="w-full py-3.5 rounded-xl text-sm font-extrabold transition-all hover:opacity-90"
style={{ background: product.accentColor, color: product.bgFrom }}
>
</button>
)}
<p className="text-center text-xs mt-2" style={{ color: 'rgba(255,255,255,0.3)' }}> <p className="text-center text-xs mt-2" style={{ color: 'rgba(255,255,255,0.3)' }}>
</p> </p>
</div> </div>
</div> </div>