981 lines
32 KiB
PHP
981 lines
32 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Api\Admin\Barobill;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\Barobill\BarobillMember;
|
|
use App\Models\Tenants\Tenant;
|
|
use App\Services\Barobill\BarobillService;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Http\Response;
|
|
use Illuminate\Support\Facades\Hash;
|
|
use Illuminate\Support\Facades\Log;
|
|
use Illuminate\Validation\Rule;
|
|
|
|
class BarobillMemberController extends Controller
|
|
{
|
|
public function __construct(
|
|
protected BarobillService $barobillService
|
|
) {}
|
|
|
|
// 바로빌 파트너사 (본사) 테넌트 ID
|
|
private const HEADQUARTERS_TENANT_ID = 1;
|
|
|
|
/**
|
|
* 회원사 조회 및 비밀번호 검증 헬퍼
|
|
*
|
|
* 회원사의 서버 모드에 따라 BarobillService의 서버 모드도 자동 전환합니다.
|
|
*
|
|
* @return BarobillMember|JsonResponse 회원사 객체 또는 에러 응답
|
|
*/
|
|
private function validateMemberForUrlApi(int $id): BarobillMember|JsonResponse
|
|
{
|
|
$member = BarobillMember::find($id);
|
|
|
|
if (! $member) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => '회원사를 찾을 수 없습니다.',
|
|
], 404);
|
|
}
|
|
|
|
if (empty($member->barobill_pwd)) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => '바로빌 비밀번호가 설정되지 않았습니다. 회원사 정보를 수정하여 비밀번호를 입력해주세요.',
|
|
'error_code' => 'MISSING_PASSWORD',
|
|
], 422);
|
|
}
|
|
|
|
// 회원사의 서버 모드로 BarobillService 전환
|
|
$this->barobillService->setServerMode($member->server_mode ?? 'test');
|
|
|
|
return $member;
|
|
}
|
|
|
|
/**
|
|
* 회원사 목록 조회
|
|
*
|
|
* - 테넌트 1(본사)이면 자동으로 모든 회원사 표시
|
|
* - 다른 테넌트면 해당 테넌트의 회원사만 표시
|
|
*
|
|
* @param all_tenants bool 전체 테넌트 조회 모드 (수동 선택용)
|
|
*/
|
|
public function index(Request $request): JsonResponse|Response
|
|
{
|
|
$tenantId = session('selected_tenant_id');
|
|
$allTenants = $request->boolean('all_tenants', false);
|
|
|
|
// 테넌트 1(본사)이면 자동으로 전체 테넌트 모드
|
|
$isHeadquarters = $tenantId == self::HEADQUARTERS_TENANT_ID;
|
|
|
|
// 본사이면 barobill_members 미등록 테넌트에 기본 레코드 자동 생성
|
|
if ($isHeadquarters || $allTenants) {
|
|
$existingTenantIds = BarobillMember::pluck('tenant_id')->toArray();
|
|
$missingTenants = Tenant::whereNotIn('id', $existingTenantIds)->get();
|
|
|
|
foreach ($missingTenants as $tenant) {
|
|
BarobillMember::create([
|
|
'tenant_id' => $tenant->id,
|
|
'biz_no' => $tenant->business_num ?? '',
|
|
'corp_name' => $tenant->company_name,
|
|
'ceo_name' => $tenant->ceo_name ?? '',
|
|
'barobill_id' => '',
|
|
'barobill_pwd' => '',
|
|
'status' => 'pending',
|
|
'server_mode' => 'test',
|
|
]);
|
|
}
|
|
}
|
|
|
|
$query = BarobillMember::query()
|
|
// 본사(테넌트 1)이거나 전체 테넌트 모드일 때는 필터 없음
|
|
->when(! $isHeadquarters && ! $allTenants && $tenantId, fn ($q) => $q->where('tenant_id', $tenantId))
|
|
->when($request->search, function ($q, $search) {
|
|
$q->where(function ($q) use ($search) {
|
|
$q->where('corp_name', 'like', "%{$search}%")
|
|
->orWhere('biz_no', 'like', "%{$search}%")
|
|
->orWhere('barobill_id', 'like', "%{$search}%")
|
|
->orWhere('manager_name', 'like', "%{$search}%");
|
|
});
|
|
})
|
|
->when($request->status, fn ($q, $status) => $q->where('status', $status))
|
|
->with('tenant:id,company_name')
|
|
->orderBy('created_at', 'desc');
|
|
|
|
$members = $query->paginate($request->integer('per_page', 15));
|
|
|
|
// 본사이거나 전체 테넌트 모드면 테넌트 컬럼 표시
|
|
$showAllTenants = $isHeadquarters || $allTenants;
|
|
|
|
// HTMX 요청 시 HTML 반환
|
|
if ($request->header('HX-Request')) {
|
|
return response(
|
|
view('barobill.members.partials.table', [
|
|
'members' => $members,
|
|
'allTenants' => $showAllTenants,
|
|
])->render(),
|
|
200,
|
|
['Content-Type' => 'text/html']
|
|
);
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'data' => $members->items(),
|
|
'meta' => [
|
|
'current_page' => $members->currentPage(),
|
|
'last_page' => $members->lastPage(),
|
|
'per_page' => $members->perPage(),
|
|
'total' => $members->total(),
|
|
],
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 회원사 등록
|
|
*
|
|
* 1. 바로빌 API를 통해 회원사 등록 (RegistCorp)
|
|
* 2. API 성공 시 로컬 DB에 저장
|
|
*
|
|
* @param tenant_id int 테넌트 ID (전체 테넌트 모드에서 직접 지정)
|
|
*/
|
|
public function store(Request $request): JsonResponse
|
|
{
|
|
// 요청에 tenant_id가 있으면 사용, 없으면 세션에서 가져오기
|
|
$tenantId = $request->filled('tenant_id')
|
|
? $request->integer('tenant_id')
|
|
: session('selected_tenant_id');
|
|
|
|
if (! $tenantId) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => '테넌트를 선택해주세요.',
|
|
], 400);
|
|
}
|
|
|
|
$validated = $request->validate([
|
|
'tenant_id' => 'nullable|integer|exists:tenants,id',
|
|
'biz_no' => [
|
|
'required',
|
|
'string',
|
|
'max:20',
|
|
Rule::unique('barobill_members')->where(function ($query) use ($tenantId) {
|
|
return $query->where('tenant_id', $tenantId);
|
|
}),
|
|
],
|
|
'corp_name' => 'required|string|max:100',
|
|
'ceo_name' => 'required|string|max:50',
|
|
'addr' => 'nullable|string|max:255',
|
|
'biz_type' => 'nullable|string|max:50',
|
|
'biz_class' => 'nullable|string|max:50',
|
|
'barobill_id' => 'required|string|max:50',
|
|
'barobill_pwd' => 'required|string|max:255',
|
|
'manager_name' => 'nullable|string|max:50',
|
|
'manager_email' => 'nullable|email|max:100',
|
|
'manager_hp' => 'nullable|string|max:20',
|
|
'tel' => 'nullable|string|max:20',
|
|
'post_num' => 'nullable|string|max:10',
|
|
'status' => 'nullable|in:active,inactive,pending',
|
|
'skip_api' => 'nullable|boolean', // API 호출 스킵 옵션 (테스트용)
|
|
], [
|
|
'tenant_id.exists' => '유효하지 않은 테넌트입니다.',
|
|
'biz_no.required' => '사업자번호를 입력해주세요.',
|
|
'biz_no.unique' => '이미 등록된 사업자번호입니다.',
|
|
'corp_name.required' => '상호명을 입력해주세요.',
|
|
'ceo_name.required' => '대표자명을 입력해주세요.',
|
|
'barobill_id.required' => '바로빌 아이디를 입력해주세요.',
|
|
'barobill_pwd.required' => '비밀번호를 입력해주세요.',
|
|
]);
|
|
|
|
$skipApi = $validated['skip_api'] ?? false;
|
|
unset($validated['skip_api']);
|
|
|
|
// 바로빌 API 호출 (skip_api가 false일 때만)
|
|
if (! $skipApi) {
|
|
$apiResult = $this->barobillService->registCorp([
|
|
'biz_no' => $validated['biz_no'],
|
|
'corp_name' => $validated['corp_name'],
|
|
'ceo_name' => $validated['ceo_name'],
|
|
'biz_type' => $validated['biz_type'] ?? '',
|
|
'biz_class' => $validated['biz_class'] ?? '',
|
|
'addr' => $validated['addr'] ?? '',
|
|
'post_num' => $validated['post_num'] ?? '',
|
|
'barobill_id' => $validated['barobill_id'],
|
|
'barobill_pwd' => $validated['barobill_pwd'],
|
|
'manager_name' => $validated['manager_name'] ?? '',
|
|
'manager_email' => $validated['manager_email'] ?? '',
|
|
'manager_hp' => $validated['manager_hp'] ?? '',
|
|
'tel' => $validated['tel'] ?? '',
|
|
]);
|
|
|
|
if (! $apiResult['success']) {
|
|
Log::error('바로빌 회원사 등록 API 실패', [
|
|
'biz_no' => $validated['biz_no'],
|
|
'error' => $apiResult['error'] ?? 'Unknown error',
|
|
'error_code' => $apiResult['error_code'] ?? null,
|
|
]);
|
|
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => '바로빌 회원사 등록에 실패했습니다.',
|
|
'error' => $apiResult['error'] ?? '알 수 없는 오류가 발생했습니다.',
|
|
'error_code' => $apiResult['error_code'] ?? null,
|
|
], 422);
|
|
}
|
|
|
|
Log::info('바로빌 회원사 등록 API 성공', [
|
|
'biz_no' => $validated['biz_no'],
|
|
'api_response' => $apiResult['data'] ?? null,
|
|
]);
|
|
}
|
|
|
|
// 로컬 DB에 저장 (비밀번호는 모델의 encrypted cast로 자동 암호화됨)
|
|
$validated['tenant_id'] = $tenantId; // 항상 계산된 tenantId 사용
|
|
$validated['status'] = $validated['status'] ?? 'active';
|
|
unset($validated['tel'], $validated['post_num']); // DB에 없는 필드 제거
|
|
|
|
$member = BarobillMember::create($validated);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => $skipApi
|
|
? '회원사가 등록되었습니다. (API 스킵)'
|
|
: '바로빌 회원사 등록이 완료되었습니다.',
|
|
'data' => $member,
|
|
], 201);
|
|
}
|
|
|
|
/**
|
|
* 회원사 상세 조회
|
|
*/
|
|
public function show(Request $request, int $id): JsonResponse
|
|
{
|
|
$member = BarobillMember::with('tenant:id,company_name')->find($id);
|
|
|
|
if (! $member) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => '회원사를 찾을 수 없습니다.',
|
|
], 404);
|
|
}
|
|
|
|
// HTMX 요청 시 HTML 반환
|
|
if ($request->header('HX-Request')) {
|
|
return response()->json([
|
|
'html' => view('barobill.members.partials.detail', compact('member'))->render(),
|
|
]);
|
|
}
|
|
|
|
// 비밀번호 설정 여부 추가 (encrypted cast 복호화 실패 대비)
|
|
$memberData = $member->toArray();
|
|
try {
|
|
$memberData['has_password'] = ! empty($member->barobill_pwd);
|
|
} catch (\Throwable $e) {
|
|
$memberData['has_password'] = ! empty($member->getRawOriginal('barobill_pwd'));
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'data' => $memberData,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 회원사 수정
|
|
*
|
|
* 비밀번호는 선택적으로 업데이트 가능 (기존 Hash 저장 데이터 호환)
|
|
*/
|
|
public function update(Request $request, int $id): JsonResponse
|
|
{
|
|
$member = BarobillMember::find($id);
|
|
|
|
if (! $member) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => '회원사를 찾을 수 없습니다.',
|
|
], 404);
|
|
}
|
|
|
|
$validated = $request->validate([
|
|
'corp_name' => 'required|string|max:100',
|
|
'ceo_name' => 'required|string|max:50',
|
|
'addr' => 'nullable|string|max:255',
|
|
'biz_type' => 'nullable|string|max:50',
|
|
'biz_class' => 'nullable|string|max:50',
|
|
'manager_name' => 'nullable|string|max:50',
|
|
'manager_email' => 'nullable|email|max:100',
|
|
'manager_hp' => 'nullable|string|max:20',
|
|
'status' => 'nullable|in:active,inactive,pending',
|
|
'barobill_id' => 'nullable|string|max:50',
|
|
'barobill_pwd' => 'nullable|string|max:255',
|
|
]);
|
|
|
|
// 비어있으면 제외 (기존 값 유지)
|
|
if (empty($validated['barobill_id'])) {
|
|
unset($validated['barobill_id']);
|
|
}
|
|
if (empty($validated['barobill_pwd'])) {
|
|
unset($validated['barobill_pwd']);
|
|
}
|
|
|
|
$member->update($validated);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => '회원사 정보가 수정되었습니다.',
|
|
'data' => $member->fresh(),
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 회원사 삭제
|
|
*/
|
|
public function destroy(int $id): JsonResponse
|
|
{
|
|
$member = BarobillMember::find($id);
|
|
|
|
if (! $member) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => '회원사를 찾을 수 없습니다.',
|
|
], 404);
|
|
}
|
|
|
|
$member->delete();
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => '회원사가 삭제되었습니다.',
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 통계 조회
|
|
*
|
|
* - 테넌트 1(본사)이면 자동으로 전체 회원사 통계
|
|
* - 다른 테넌트면 해당 테넌트의 회원사만 통계
|
|
*/
|
|
public function stats(Request $request): JsonResponse|Response
|
|
{
|
|
$tenantId = session('selected_tenant_id');
|
|
$allTenants = $request->boolean('all_tenants', false);
|
|
|
|
// 테넌트 1(본사)이면 자동으로 전체 테넌트 모드
|
|
$isHeadquarters = $tenantId == self::HEADQUARTERS_TENANT_ID;
|
|
|
|
$query = BarobillMember::query()
|
|
->when(! $isHeadquarters && ! $allTenants && $tenantId, fn ($q) => $q->where('tenant_id', $tenantId));
|
|
|
|
$stats = [
|
|
'total' => (clone $query)->count(),
|
|
'active' => (clone $query)->where('status', 'active')->count(),
|
|
'inactive' => (clone $query)->where('status', 'inactive')->count(),
|
|
'pending' => (clone $query)->where('status', 'pending')->count(),
|
|
];
|
|
|
|
// HTMX 요청 시 HTML 반환
|
|
if ($request->header('HX-Request')) {
|
|
return response(
|
|
view('barobill.members.partials.stats', compact('stats'))->render(),
|
|
200,
|
|
['Content-Type' => 'text/html']
|
|
);
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'data' => $stats,
|
|
]);
|
|
}
|
|
|
|
// ========================================
|
|
// 바로빌 URL 조회 API (리다이렉트용)
|
|
// ========================================
|
|
|
|
/**
|
|
* 계좌 등록 URL 조회
|
|
*
|
|
* 회원사가 계좌를 등록할 수 있는 바로빌 페이지 URL을 반환합니다.
|
|
*/
|
|
public function getBankAccountUrl(Request $request, int $id): JsonResponse
|
|
{
|
|
$member = $this->validateMemberForUrlApi($id);
|
|
if ($member instanceof JsonResponse) {
|
|
return $member;
|
|
}
|
|
|
|
$result = $this->barobillService->getBankAccountScrapRequestUrl(
|
|
$member->biz_no,
|
|
$member->barobill_id,
|
|
$member->barobill_pwd
|
|
);
|
|
|
|
if (! $result['success']) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => '계좌 등록 URL을 가져오는데 실패했습니다.',
|
|
'error' => $result['error'] ?? null,
|
|
], 422);
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'data' => [
|
|
'url' => $result['data'],
|
|
'type' => 'bank_account_register',
|
|
],
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 계좌 관리 URL 조회
|
|
*
|
|
* 회원사가 등록된 계좌를 관리할 수 있는 바로빌 페이지 URL을 반환합니다.
|
|
*/
|
|
public function getBankAccountManageUrl(Request $request, int $id): JsonResponse
|
|
{
|
|
$member = $this->validateMemberForUrlApi($id);
|
|
if ($member instanceof JsonResponse) {
|
|
return $member;
|
|
}
|
|
|
|
$result = $this->barobillService->getBankAccountManagementUrl(
|
|
$member->biz_no,
|
|
$member->barobill_id,
|
|
$member->barobill_pwd
|
|
);
|
|
|
|
if (! $result['success']) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => '계좌 관리 URL을 가져오는데 실패했습니다.',
|
|
'error' => $result['error'] ?? null,
|
|
], 422);
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'data' => [
|
|
'url' => $result['data'],
|
|
'type' => 'bank_account_manage',
|
|
],
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 인증서 등록 URL 조회
|
|
*
|
|
* 회원사가 공동인증서를 등록할 수 있는 바로빌 페이지 URL을 반환합니다.
|
|
*/
|
|
public function getCertificateUrl(Request $request, int $id): JsonResponse
|
|
{
|
|
$member = $this->validateMemberForUrlApi($id);
|
|
if ($member instanceof JsonResponse) {
|
|
return $member;
|
|
}
|
|
|
|
$result = $this->barobillService->getCertificateRegistUrl(
|
|
$member->biz_no,
|
|
$member->barobill_id,
|
|
$member->barobill_pwd
|
|
);
|
|
|
|
if (! $result['success']) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => '인증서 등록 URL을 가져오는데 실패했습니다.',
|
|
'error' => $result['error'] ?? null,
|
|
], 422);
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'data' => [
|
|
'url' => $result['data'],
|
|
'type' => 'certificate_register',
|
|
],
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 현금충전 URL 조회
|
|
*
|
|
* 회원사가 바로빌 포인트를 충전할 수 있는 페이지 URL을 반환합니다.
|
|
*/
|
|
public function getCashChargeUrl(Request $request, int $id): JsonResponse
|
|
{
|
|
$member = $this->validateMemberForUrlApi($id);
|
|
if ($member instanceof JsonResponse) {
|
|
return $member;
|
|
}
|
|
|
|
$result = $this->barobillService->getCashChargeUrl(
|
|
$member->biz_no,
|
|
$member->barobill_id,
|
|
$member->barobill_pwd
|
|
);
|
|
|
|
if (! $result['success']) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => '충전 URL을 가져오는데 실패했습니다.',
|
|
'error' => $result['error'] ?? null,
|
|
], 422);
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'data' => [
|
|
'url' => $result['data'],
|
|
'type' => 'cash_charge',
|
|
],
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 인증서 상태 조회
|
|
*
|
|
* 회원사의 공동인증서 등록 상태를 확인합니다.
|
|
*/
|
|
public function getCertificateStatus(int $id): JsonResponse
|
|
{
|
|
$member = BarobillMember::find($id);
|
|
|
|
if (! $member) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => '회원사를 찾을 수 없습니다.',
|
|
], 404);
|
|
}
|
|
|
|
// 인증서 유효성 확인
|
|
$validResult = $this->barobillService->checkCertificateValid($member->biz_no);
|
|
|
|
// 인증서 만료일 조회
|
|
$expireResult = $this->barobillService->getCertificateExpireDate($member->biz_no);
|
|
|
|
// 인증서 등록일 조회
|
|
$registResult = $this->barobillService->getCertificateRegistDate($member->biz_no);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'data' => [
|
|
'is_valid' => $validResult['success'] && $validResult['data'] > 0,
|
|
'expire_date' => $expireResult['success'] ? $expireResult['data'] : null,
|
|
'regist_date' => $registResult['success'] ? $registResult['data'] : null,
|
|
],
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 충전 잔액 조회
|
|
*
|
|
* 회원사의 바로빌 충전 잔액을 확인합니다.
|
|
*/
|
|
public function getBalance(int $id): JsonResponse
|
|
{
|
|
$member = BarobillMember::find($id);
|
|
|
|
if (! $member) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => '회원사를 찾을 수 없습니다.',
|
|
], 404);
|
|
}
|
|
|
|
$result = $this->barobillService->getBalanceCostAmount($member->biz_no);
|
|
|
|
if (! $result['success']) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => '잔액 조회에 실패했습니다.',
|
|
'error' => $result['error'] ?? null,
|
|
], 422);
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'data' => [
|
|
'balance' => $result['data'],
|
|
],
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 등록 계좌 목록 조회
|
|
*
|
|
* 회원사가 바로빌에 등록한 계좌 목록을 조회합니다.
|
|
*/
|
|
public function getBankAccounts(int $id): JsonResponse
|
|
{
|
|
$member = BarobillMember::find($id);
|
|
|
|
if (! $member) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => '회원사를 찾을 수 없습니다.',
|
|
], 404);
|
|
}
|
|
|
|
$result = $this->barobillService->getBankAccounts($member->biz_no);
|
|
|
|
if (! $result['success']) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => '계좌 목록 조회에 실패했습니다.',
|
|
'error' => $result['error'] ?? null,
|
|
], 422);
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'data' => $result['data'],
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 계좌 입출금내역 URL 조회
|
|
*/
|
|
public function getBankAccountLogUrl(Request $request, int $id): JsonResponse
|
|
{
|
|
$member = $this->validateMemberForUrlApi($id);
|
|
if ($member instanceof JsonResponse) {
|
|
return $member;
|
|
}
|
|
|
|
$result = $this->barobillService->getBankAccountLogUrl(
|
|
$member->biz_no,
|
|
$member->barobill_id,
|
|
$member->barobill_pwd
|
|
);
|
|
|
|
if (! $result['success']) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => '입출금내역 URL을 가져오는데 실패했습니다.',
|
|
'error' => $result['error'] ?? null,
|
|
], 422);
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'data' => [
|
|
'url' => $result['data'],
|
|
'type' => 'bank_account_log',
|
|
],
|
|
]);
|
|
}
|
|
|
|
// ========================================
|
|
// 카드조회 관련 API
|
|
// ========================================
|
|
|
|
/**
|
|
* 카드 등록 URL 조회
|
|
*
|
|
* 회원사가 카드를 등록할 수 있는 바로빌 페이지 URL을 반환합니다.
|
|
*/
|
|
public function getCardUrl(Request $request, int $id): JsonResponse
|
|
{
|
|
$member = $this->validateMemberForUrlApi($id);
|
|
if ($member instanceof JsonResponse) {
|
|
return $member;
|
|
}
|
|
|
|
$result = $this->barobillService->getCardScrapRequestUrl(
|
|
$member->biz_no,
|
|
$member->barobill_id,
|
|
$member->barobill_pwd
|
|
);
|
|
|
|
if (! $result['success']) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => '카드 등록 URL을 가져오는데 실패했습니다.',
|
|
'error' => $result['error'] ?? null,
|
|
], 422);
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'data' => [
|
|
'url' => $result['data'],
|
|
'type' => 'card_register',
|
|
],
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 카드 관리 URL 조회
|
|
*
|
|
* 회원사가 등록된 카드를 관리할 수 있는 바로빌 페이지 URL을 반환합니다.
|
|
*/
|
|
public function getCardManageUrl(Request $request, int $id): JsonResponse
|
|
{
|
|
$member = $this->validateMemberForUrlApi($id);
|
|
if ($member instanceof JsonResponse) {
|
|
return $member;
|
|
}
|
|
|
|
$result = $this->barobillService->getCardManagementUrl(
|
|
$member->biz_no,
|
|
$member->barobill_id,
|
|
$member->barobill_pwd
|
|
);
|
|
|
|
if (! $result['success']) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => '카드 관리 URL을 가져오는데 실패했습니다.',
|
|
'error' => $result['error'] ?? null,
|
|
], 422);
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'data' => [
|
|
'url' => $result['data'],
|
|
'type' => 'card_manage',
|
|
],
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 카드 사용내역 URL 조회
|
|
*/
|
|
public function getCardLogUrl(Request $request, int $id): JsonResponse
|
|
{
|
|
$member = $this->validateMemberForUrlApi($id);
|
|
if ($member instanceof JsonResponse) {
|
|
return $member;
|
|
}
|
|
|
|
$result = $this->barobillService->getCardLogUrl(
|
|
$member->biz_no,
|
|
$member->barobill_id,
|
|
$member->barobill_pwd
|
|
);
|
|
|
|
if (! $result['success']) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => '카드 사용내역 URL을 가져오는데 실패했습니다.',
|
|
'error' => $result['error'] ?? null,
|
|
], 422);
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'data' => [
|
|
'url' => $result['data'],
|
|
'type' => 'card_log',
|
|
],
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 등록 카드 목록 조회
|
|
*
|
|
* 회원사가 바로빌에 등록한 카드 목록을 조회합니다.
|
|
*/
|
|
public function getCards(int $id): JsonResponse
|
|
{
|
|
$member = BarobillMember::find($id);
|
|
|
|
if (! $member) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => '회원사를 찾을 수 없습니다.',
|
|
], 404);
|
|
}
|
|
|
|
$result = $this->barobillService->getCards($member->biz_no);
|
|
|
|
if (! $result['success']) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => '카드 목록 조회에 실패했습니다.',
|
|
'error' => $result['error'] ?? null,
|
|
], 422);
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'data' => $result['data'],
|
|
]);
|
|
}
|
|
|
|
// ========================================
|
|
// 전자세금계산서 관련 API
|
|
// ========================================
|
|
|
|
/**
|
|
* 세금계산서 발행 URL 조회
|
|
*/
|
|
public function getTaxInvoiceUrl(Request $request, int $id): JsonResponse
|
|
{
|
|
$member = $this->validateMemberForUrlApi($id);
|
|
if ($member instanceof JsonResponse) {
|
|
return $member;
|
|
}
|
|
|
|
$result = $this->barobillService->getTaxInvoiceIssueUrl(
|
|
$member->biz_no,
|
|
$member->barobill_id,
|
|
$member->barobill_pwd
|
|
);
|
|
|
|
if (! $result['success']) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => '세금계산서 발행 URL을 가져오는데 실패했습니다.',
|
|
'error' => $result['error'] ?? null,
|
|
], 422);
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'data' => [
|
|
'url' => $result['data'],
|
|
'type' => 'tax_invoice_issue',
|
|
],
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 세금계산서 목록 URL 조회
|
|
*/
|
|
public function getTaxInvoiceListUrl(Request $request, int $id): JsonResponse
|
|
{
|
|
$member = $this->validateMemberForUrlApi($id);
|
|
if ($member instanceof JsonResponse) {
|
|
return $member;
|
|
}
|
|
|
|
$result = $this->barobillService->getTaxInvoiceListUrl(
|
|
$member->biz_no,
|
|
$member->barobill_id,
|
|
$member->barobill_pwd
|
|
);
|
|
|
|
if (! $result['success']) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => '세금계산서 목록 URL을 가져오는데 실패했습니다.',
|
|
'error' => $result['error'] ?? null,
|
|
], 422);
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'data' => [
|
|
'url' => $result['data'],
|
|
'type' => 'tax_invoice_list',
|
|
],
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 서비스 코드 목록 조회 (카드사/은행)
|
|
*/
|
|
public function getServiceCodes(): JsonResponse
|
|
{
|
|
return response()->json([
|
|
'success' => true,
|
|
'data' => [
|
|
'card_companies' => BarobillService::$cardCompanyCodes,
|
|
'banks' => BarobillService::$bankCodes,
|
|
],
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 회원사별 서버 모드 변경
|
|
*
|
|
* 특정 회원사의 바로빌 서버 모드(테스트/운영)를 변경합니다.
|
|
* 주의: 운영 서버로 전환 시 요금이 부과됩니다.
|
|
*/
|
|
public function updateServerMode(Request $request, int $id): JsonResponse
|
|
{
|
|
$member = BarobillMember::find($id);
|
|
|
|
if (! $member) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => '회원사를 찾을 수 없습니다.',
|
|
], 404);
|
|
}
|
|
|
|
$validated = $request->validate([
|
|
'server_mode' => 'required|in:test,production',
|
|
'confirmed' => 'required|boolean',
|
|
], [
|
|
'server_mode.required' => '서버 모드를 선택해주세요.',
|
|
'server_mode.in' => '서버 모드는 test 또는 production 이어야 합니다.',
|
|
'confirmed.required' => '경고 확인이 필요합니다.',
|
|
]);
|
|
|
|
// 확인 체크
|
|
if (! $validated['confirmed']) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => '서버 변경 경고를 확인해주세요.',
|
|
], 422);
|
|
}
|
|
|
|
$oldMode = $member->server_mode ?? 'test';
|
|
$newMode = $validated['server_mode'];
|
|
|
|
// 변경 없으면 바로 반환
|
|
if ($oldMode === $newMode) {
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => '서버 모드가 이미 '.($newMode === 'test' ? '테스트' : '운영').' 서버입니다.',
|
|
'data' => $member,
|
|
]);
|
|
}
|
|
|
|
$member->update(['server_mode' => $newMode]);
|
|
|
|
Log::info('바로빌 회원사 서버 모드 변경', [
|
|
'member_id' => $id,
|
|
'biz_no' => $member->biz_no,
|
|
'corp_name' => $member->corp_name,
|
|
'old_mode' => $oldMode,
|
|
'new_mode' => $newMode,
|
|
'user_id' => auth()->id(),
|
|
]);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => ($newMode === 'test' ? '테스트' : '운영').' 서버로 변경되었습니다.',
|
|
'data' => $member->fresh(),
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 회원사별 서버 모드 조회
|
|
*/
|
|
public function getServerMode(int $id): JsonResponse
|
|
{
|
|
$member = BarobillMember::find($id);
|
|
|
|
if (! $member) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => '회원사를 찾을 수 없습니다.',
|
|
], 404);
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'data' => [
|
|
'server_mode' => $member->server_mode ?? 'test',
|
|
'server_mode_label' => $member->server_mode_label,
|
|
],
|
|
]);
|
|
}
|
|
}
|