백로그
0할 일
0진행 중
0리뷰
1코호트 일반결제 — Toss::PaymentService + checkout/confirm + Payment/CohortEnrollment 생성 + 테스트
## 목표 PRD Section 11.2 기반 Toss::PaymentService 구현. 코호트 1회성 결제. checkout 파라미터 생성, confirm 처리, Payment + CohortEnrollment 생성. ## 현재 상태 - Toss::Client 구현 완료 (confirm_payment, cancel_payment, get_payment) - Payment 모델: belongs_to :user, belongs_to :cohort(optional). toss_payment_key, toss_order_id, amount, status enum - CohortEnrollment 모델: belongs_to :cohort, belongs_to :user. status enum - Cohort 모델: name, price_cents 등 ## PRD 코드 (Section 11.2) ```ruby class Toss::PaymentService def initialize(user:, plan:, cohort: nil) @user = user @plan = plan @cohort = cohort @client = Toss::Client.new end def checkout_params { amount: amount, orderId: generate_order_id, orderName: order_name, customerKey: @user.toss_customer_key, customerName: @user.name, customerEmail: @user.email_address, successUrl: "#{ENV["APP_URL"]}/payments/success", failUrl: "#{ENV["APP_URL"]}/payments/fail" } end def confirm(payment_key:, order_id:) result = @client.confirm_payment(payment_key: payment_key, order_id: order_id, amount: amount) return Result.failure(result.error_message) unless result.success? save_payment(result.data, payment_key, order_id) activate_plan Result.success end private def amount case @plan when "cohort" then @cohort&.price_cents || 2_990_000 else raise "일반결제는 cohort만 지원" end end def order_name = "VALUEIT #{@cohort&.name || @plan.upcase}" def generate_order_id = "valueit-#{@plan}-#{@user.id}-#{Time.current.to_i}" def save_payment(data, payment_key, order_id) @user.payments.create!( cohort: @cohort, toss_payment_key: payment_key, toss_order_id: order_id, toss_order_name: order_name, amount: amount, payment_method: data["method"], card_company: data.dig("card", "company"), card_number: data.dig("card", "number"), status: :done, paid_at: Time.current ) end def activate_plan if @plan == "cohort" && @cohort @user.cohort_enrollments.create!(cohort: @cohort, status: :active, paid_at: Time.current) @user.update!(role: :cohort) end end end ``` ## 구현 사항 1. **app/services/toss/payment_service.rb** — PRD 코드 기반 2. **Result 패턴**: 간단한 Result struct (success/failure) — 또는 OpenStruct 사용 3. **⚠️ PRD의 `@user.email`을 `@user.email_address`로 변경** (Rails 8 auth generator가 email_address 컬럼 사용) 4. **⚠️ PRD의 `plan:` 컬럼은 payments 테이블에 없음** — save_payment에서 plan 컬럼 제거 5. **의존성 주입**: client: 파라미터로 테스트 용이성 6. **테스트**: checkout_params 생성, confirm 성공(Payment+CohortEnrollment 생성, User role 변경), confirm 실패 ### ⚠️ 주의 - services/toss/ 범위만 (developer-2는 launch/ 작업 중) - Payment, CohortEnrollment, User, Cohort 모델 건드리지 않기 - email_address 컬럼명 주의 (PRD의 email과 다름) ### 완료 기준 - checkout 파라미터 생성 - confirm → Payment + CohortEnrollment 생성 + User role :cohort - 실패 시 Result.failure - bin/rails test 전체 통과