부모 티켓
1개 티켓

백로그

0
티켓 없음

할 일

0
티켓 없음

진행 중

0
티켓 없음

리뷰

0
티켓 없음

완료 (전체)

1
보통 d109c3f2
서브 티켓 [리퍼럴 PR4] 진단 크레딧 개인 구매 (PG 결제, 3,000원)

진단 크레딧 구매 서비스 + 컨트롤러 + 라우트

## 작업 내용 ### 1. Payments::DiagnosisCreditPurchaseService (`app/services/payments/diagnosis_credit_purchase_service.rb`) 기존 `Payments::CreditPurchaseService` (워크스페이스용)를 참고하여 개인 진단 크레딧 구매 서비스 생성. ```ruby module Payments class DiagnosisCreditPurchaseService PRICE_PER_CREDIT = 3_000 # 원 (VAT 포함) def initialize(user:, quantity: 1, locale: "ko") @user = user @quantity = quantity.to_i @locale = locale end # PG 결제 준비 def prepare_checkout! amount = @quantity * PRICE_PER_CREDIT order_id = OrderIdGenerator.generate(payment_type: "DIAG_CREDIT", user_id: @user.id) payment = Payment.create!( user: @user, order_id: order_id, amount: amount, currency: "KRW", provider: "toss_payments", payment_type: "diagnosis_credit", description: "진단 크레딧 #{@quantity}개", status: "pending", metadata: { "quantity" => @quantity, "product_type" => "diagnosis_credit" } ) { payment_id: payment.id, order_id: order_id, amount: amount, order_name: "진단 크레딧 #{@quantity}개", customer_key: "customer_#{@user.id}" } end # 결제 완료 후 크레딧 지급 def self.complete_purchase!(payment) quantity = payment.metadata&.dig("quantity").to_i return unless quantity > 0 return unless payment.metadata&.dig("product_type") == "diagnosis_credit" user = payment.user credit = user.ensure_credit! payment.with_lock do return if CreditTransaction.exists?(payment_id: payment.id, credit_type: "diagnosis") credit.add_diagnosis!( quantity, description: "진단 크레딧 구매 (#{quantity}개)", payment: payment ) end end end end ``` ### 2. Payment 모델 수정 - `payment_type` validation에 `diagnosis_credit` 추가 (기존 validation 확인 후) ### 3. ConfirmationService 수정 (`app/services/payments/confirmation_service.rb`) - 결제 완료 후 처리 로직에 diagnosis_credit 케이스 추가: ```ruby # 기존 complete_purchase 로직 안에 if payment.payment_type == "diagnosis_credit" DiagnosisCreditPurchaseService.complete_purchase!(payment) end ``` ### 4. DiagnosisCreditsController (`app/controllers/diagnosis_credits_controller.rb`) ```ruby class DiagnosisCreditsController < ApplicationController layout "authenticated" def new # 구매 페이지 표시 @quantity = (params[:quantity] || 1).to_i @price_per_credit = Payments::DiagnosisCreditPurchaseService::PRICE_PER_CREDIT @total = @quantity * @price_per_credit end def create quantity = (params[:quantity] || 1).to_i service = Payments::DiagnosisCreditPurchaseService.new( user: Current.user, quantity: quantity, locale: I18n.locale ) checkout_data = service.prepare_checkout! render json: checkout_data end end ``` ### 5. 라우트 추가 (`config/routes.rb`) locale scope 내부에: ```ruby resources :diagnosis_credits, only: %i[new create] ``` ### 6. Product seed (선택) 기존 Product 모델 확인 후 필요하면 seed 추가. ### 7. TDD - `test/services/payments/diagnosis_credit_purchase_service_test.rb`: - prepare_checkout!: Payment(pending) 생성, amount 검증 - complete_purchase!: diagnosis_balance 증가, 멱등성 검증 - `test/controllers/diagnosis_credits_controller_test.rb`: - GET new: 200 응답 - POST create: checkout_data JSON 반환 ## 완료 기준 - 진단 크레딧 구매 → PG 결제 → diagnosis_balance 증가 - 멱등성 보장 (중복 결제 방지) - 테스트 통과

D
developer-1
3 months