validate([ 'oid' => ['required','string','max:64'], 'method' => ['required','in:card,vact,phone'], 'card_kind' => ['nullable','in:general,exchange'], 'phone_mode' => ['nullable','in:prod,dev'], 'is_mobile' => ['nullable','boolean'], ]); $memNo = $this->currentMemNo($request); if ($memNo <= 0) abort(403); $out = $this->service->start( $data['oid'], $memNo, $data['method'], [ 'card_kind' => $data['card_kind'] ?? null, 'phone_mode' => $data['phone_mode'] ?? null, 'is_mobile' => (bool)($data['is_mobile'] ?? false), ] ); if (($out['type'] ?? '') === 'redirect') { return view('web.payments.danal.redirect', [ 'actionUrl' => $out['start']['actionUrl'], 'params' => $out['start']['params'], 'acceptCharset' => $out['start']['acceptCharset'] ?? 'EUC-KR', ]); } return view('web.payments.danal.result', $out); } // 카드 RETURNURL public function cardReturn(Request $request) { $token = (string)$request->query('a', ''); if ($token === '') abort(404); if (($out['ok'] ?? false) && ($out['status'] ?? '') === 'paid') { $attemptId = (int)($out['meta']['attempt_id'] ?? 0); $redirect = url("/mypage/usage?attempt_id={$attemptId}"); return view('web.payments.danal.finish_top_action', [ 'action' => 'close_modal', 'title' => '결제완료', 'message' => '결제가 완료되었습니다. 구매페이지로 이동합니다.', 'redirect' => url($redirect), ]); } return view('web.payments.danal.finish_top_action', [ 'action' => 'close_modal', 'title' => '결제실패', 'message' => '결제에 실패했습니다.', ]); } // 가상계좌 RETURNURL public function vactReturn(Request $request) { $token = (string)$request->query('a', ''); if ($token === '') abort(404); $out = $this->service->handleVactReturn($token, $request->all()); if (($out['ok'] ?? false) && ($out['status'] ?? '') === 'issued') { $attemptId = (int)($out['meta']['attempt_id'] ?? 0); $redirect = url("/mypage/usage?attempt_id={$attemptId}"); return view('web.payments.danal.finish_top_action', [ 'action' => 'close_modal', 'title' => '가상계좌 발급', 'message' => '가상계좌가 발급되었습니다. 입금 후 결제가 완료됩니다. 구매페이지로 이동합니다.', 'redirect' => url($redirect), ]); } return view('web.payments.danal.finish_top_action', [ 'action' => 'close_modal', 'title' => '처리실패', 'message' => '가상계좌 처리에 실패했습니다.', ]); } // 가상계좌 NOTIURL (반드시 OK) public function vactNoti(Request $request) { $this->service->handleVactNoti($request->all()); return response('OK', 200)->header('Content-Type', 'text/plain'); } // 휴대폰 TargetURL public function phoneReturn(Request $request) { $out = $this->service->handlePhoneReturn($request->all()); if (($out['ok'] ?? false) && ($out['status'] ?? '') === 'paid') { $attemptId = (int)($out['meta']['attempt_id'] ?? 0); $redirect = url("/mypage/usage?attempt_id={$attemptId}"); return view('web.payments.danal.finish_top_action', [ 'action' => 'close_modal', 'title' => '결제완료', 'message' => '결제가 완료되었습니다. 구매페이지로 이동합니다.', 'redirect' => url($redirect), ]); } return view('web.payments.danal.finish_top_action', [ 'action' => 'close_modal', 'title' => '결제실패', 'message' => '결제에 실패했습니다.', ]); } // 휴대폰 BackURL(취소) public function phoneCancel(Request $request) { $out = $this->service->handlePhoneCancel($request->all()); return view('web.payments.danal.finish_top_action', [ 'action' => 'close_modal', 'message' => '결제가 취소되었습니다.', 'title' => '결제취소', ]); } // 카드/가상계좌 CancelURL public function cancel(Request $request) { $token = (string)$request->query('a', ''); if ($token === '') abort(404); $out = $this->service->handleCancel($token); // ✅ 취소면: iframe 닫고 showMsg 실행 if (($out['meta']['code'] ?? '') === 'CANCEL') { return view('web.payments.danal.finish_top_action', [ 'action' => 'close_modal', 'message' => '결제가 취소되었습니다.', 'title' => '결제취소', ]); } return view('web.payments.danal.result', $out); } private function currentMemNo(Request $request): int { // 프로젝트에 맞게 연결해라: // 1) Auth::user()->mem_no 가 있으면 그걸 쓰고, // 2) local 테스트용은 request('mem_no') 허용 $u = $request->user(); if ($u && isset($u->mem_no)) return (int)$u->mem_no; if (app()->environment('local')) { return (int)$request->input('mem_no', 0); } return 0; } }