데브포일 홈
DEV MODE - 실서버 영향 없음 📦 배포 관리
환불/취소 & 정산 관리
+250 XP
LEVEL 56 QUEST

환불/취소 & 정산 관리

전액/부분 환불 처리, 매출 정산 리포트 생성, 세금계산서 발행까지 결제 시스템의 마지막 퍼즐을 완성합니다.

환불 처리 로직

환불의 종류

SaaS 서비스에서 환불은 크게 두 가지로 나뉩니다. 전액 환불은 결제 금액 전체를 돌려주는 것이고, 부분 환불은 사용한 기간을 제외한 나머지 금액만 돌려줍니다. 전자상거래법에 따라 구매 후 7일 이내 청약철회 시 전액 환불이 원칙입니다.

환불 유형 적용 조건 환불 금액
전액 환불 결제 후 7일 이내 (청약철회) 결제 금액 100%
부분 환불 (일할 계산) 7일 이후 ~ 결제 주기 내 잔여 기간 비례 금액
환불 불가 이미 전액 소비된 서비스 0원 (사유 안내)
// classes/RefundService.php - 환불 처리 서비스 <?php class RefundService { private PDO $pdo; private TossBillingService $toss; private PayPalClient $paypal; public function __construct(PDO $pdo, array $config) { $this->pdo = $pdo; $this->toss = new TossBillingService($config['toss']['secret_key']); $this->paypal = new PayPalClient($config['paypal']); } /** * 환불 금액 계산 */ public function calculateRefundAmount(array $payment): array { $approvedAt = new DateTime($payment['approved_at']); $now = new DateTime(); $daysSincePurchase = $approvedAt->diff($now)->days; // 7일 이내: 전액 환불 (청약철회) if ($daysSincePurchase 7) { return [ 'type' => 'full', 'amount' => $payment['amount'], 'reason' => '청약철회 (7일 이내)', ]; } // 7일 이후: 잔여 기간 일할 계산 $totalDays = 30; // 월간 구독 기준 $usedDays = min($daysSincePurchase, $totalDays); $remainingDays = $totalDays - $usedDays; $refundAmount = (int)floor( $payment['amount'] * ($remainingDays / $totalDays) ); return [ 'type' => 'partial', 'amount' => max(0, $refundAmount), 'used_days' => $usedDays, 'remain_days' => $remainingDays, 'reason' => "부분 환불 (사용 {$usedDays}일, 잔여 {$remainingDays}일)", ]; } /** * 환불 실행 (토스 또는 PayPal 자동 분기) */ public function processRefund( int $paymentId, int $refundAmount, string $reason ): array { $stmt = $this->pdo->prepare("SELECT * FROM payments WHERE id = ?"); $stmt->execute([$paymentId]); $payment = $stmt->fetch(); if (!$payment || $payment['status'] !== 'approved') { return ['success' => false, 'error' => '환불 대상 결제를 찾을 수 없습니다']; } if ($refundAmount > $payment['amount']) { return ['success' => false, 'error' => '환불 금액이 결제 금액을 초과합니다']; } // 결제 수단에 따라 분기 if ($payment['method'] === 'paypal') { return $this->refundPayPal($payment, $refundAmount, $reason); } else { return $this->refundToss($payment, $refundAmount, $reason); } } }

토스페이먼츠 환불 API 연동

// RefundService - 토스페이먼츠 환불 메서드 private function refundToss( array $payment, int $refundAmount, string $reason ): array { $config = require 'config/payment.php'; $secretKey = $config['toss']['secret_key']; $paymentKey = $payment['payment_key']; // 토스 환불 API 호출 $ch = curl_init(); curl_setopt_array($ch, [ CURLOPT_URL => "https://api.tosspayments.com/v1/payments/{$paymentKey}/cancel", CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'Authorization: Basic ' . base64_encode($secretKey . ':'), 'Content-Type: application/json', ], CURLOPT_POSTFIELDS => json_encode([ 'cancelReason' => $reason, 'cancelAmount' => $refundAmount, // 부분 환불 시 금액 지정 ]), ]); $response = json_decode(curl_exec($ch), true); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($httpCode === 200) { // 환불 성공 → DB 업데이트 $this->recordRefund($payment, $refundAmount, $reason, 'toss'); return ['success' => true, 'refund_amount' => $refundAmount]; } return [ 'success' => false, 'error' => $response['message'] ?? '토스 환불 API 오류', ]; }
🔒
여기까지는 미리보기입니다
환불/취소 & 정산 관리
무료 가입하면 이어서 볼 수 있고, 강의를 완료할 때마다 XP와 레벨이 쌓입니다.
Google로 3초 만에 시작 →🧵 Threads로 시작무료 공개 강의 둘러보기 (Lv.1~3)