'사업자번호가 설정되지 않았거나 유효하지 않습니다.', -11102 => 'CERTKEY가 유효하지 않습니다.', -11103 => '인증서가 만료되었거나 유효하지 않습니다.', -11104 => '해당 사업자가 등록되어 있지 않습니다.', -11105 => '이미 등록된 사업자입니다.', -11106 => '아이디가 이미 존재합니다.', -11201 => '필수 파라미터가 누락되었습니다.', -25001 => '조회 결과가 없습니다.', -25005 => '조회 기간에 데이터가 없습니다.', -26001 => '공동인증서가 등록되어 있지 않습니다.', -32000 => '알 수 없는 오류가 발생했습니다.', -32001 => '사업자번호가 유효하지 않습니다.', -32002 => '아이디가 유효하지 않습니다.', -32003 => '비밀번호가 유효하지 않습니다.', -32004 => '상호명이 유효하지 않습니다.', -32005 => '대표자명이 유효하지 않습니다.', -32006 => '이메일 형식이 유효하지 않습니다.', -32010 => '이미 등록된 사업자번호입니다.', -32011 => '이미 등록된 아이디입니다.', -32012 => '이미 등록된 아이디입니다. 다른 아이디를 사용해주세요.', -32013 => '비밀번호 형식이 유효하지 않습니다. (영문/숫자/특수문자 조합 8자리 이상)', -32014 => '연락처 형식이 유효하지 않습니다.', -32020 => '파트너 사업자번호가 유효하지 않습니다.', -32021 => '파트너 인증키(CERTKEY)가 유효하지 않습니다.', -99999 => '서버 내부 오류가 발생했습니다.', ]; public function __construct() { $this->isTestMode = (bool) config('services.barobill.test_mode', true); $this->initializeConfig(); } // ========================================================================= // 설정/초기화 // ========================================================================= /** * 서버 모드 전환 (회원사별 설정 적용) */ public function switchServerMode(bool $isTestMode): self { if ($this->isTestMode !== $isTestMode) { $this->isTestMode = $isTestMode; $this->resetClients(); $this->initializeConfig(); } return $this; } /** * 서버 모드 문자열로 전환 */ public function setServerMode(string $mode): self { return $this->switchServerMode($mode === 'test'); } public function getServerMode(): string { return $this->isTestMode ? 'test' : 'production'; } /** * 설정 초기화 (서버 모드에 따른 설정 로드) */ protected function initializeConfig(): void { $dbConfig = $this->loadConfigFromDatabase(); if ($dbConfig) { $this->certKey = $dbConfig->cert_key; $this->corpNum = $dbConfig->corp_num ?? ''; $this->soapUrls = $this->buildSoapUrls($dbConfig->base_url); } else { $this->certKey = $this->isTestMode ? config('services.barobill.cert_key_test', '') : config('services.barobill.cert_key_prod', ''); $this->corpNum = config('services.barobill.corp_num', ''); $baseUrl = $this->isTestMode ? 'https://testws.baroservice.com' : 'https://ws.baroservice.com'; $this->soapUrls = $this->buildSoapUrls($baseUrl); } } protected function loadConfigFromDatabase(): ?BarobillConfig { try { return BarobillConfig::getActive($this->isTestMode); } catch (\Exception $e) { Log::warning('[BarobillSoap] DB 설정 로드 실패', ['error' => $e->getMessage()]); return null; } } protected function buildSoapUrls(string $baseUrl): array { $baseUrl = rtrim($baseUrl, '/'); return [ 'corpstate' => $baseUrl.'/CORPSTATE.asmx?WSDL', 'ti' => $baseUrl.'/TI.asmx?WSDL', 'bankaccount' => $baseUrl.'/BANKACCOUNT.asmx?WSDL', 'card' => $baseUrl.'/CARD.asmx?WSDL', 'kakaotalk' => $baseUrl.'/KAKAOTALK.asmx?WSDL', 'sms' => $baseUrl.'/SMS.asmx?WSDL', ]; } protected function resetClients(): void { $this->corpStateClient = null; $this->bankAccountClient = null; $this->cardClient = null; $this->tiClient = null; $this->kakaotalkClient = null; $this->smsClient = null; } /** * 설정 상태 확인 */ public function checkConfiguration(): array { $dbConfig = $this->loadConfigFromDatabase(); return [ 'cert_key_set' => ! empty($this->certKey), 'corp_num_set' => ! empty($this->corpNum), 'test_mode' => $this->isTestMode, 'mode_label' => $this->isTestMode ? '테스트' : '운영', 'soap_url' => $this->soapUrls['corpstate'] ?? '', 'config_source' => $dbConfig ? 'database' : 'env', ]; } /** * 회원사 설정 기반 초기화 (동기화 서비스에서 사용) */ public function initForMember(BarobillMember $member): self { $this->switchServerMode($member->isTestMode()); return $this; } // ========================================================================= // SOAP 클라이언트 // ========================================================================= protected function createSoapClient(string $wsdlUrl): ?SoapClient { try { $context = stream_context_create([ 'ssl' => [ 'verify_peer' => false, 'verify_peer_name' => false, 'allow_self_signed' => true, ], ]); return new SoapClient($wsdlUrl, [ 'trace' => true, 'encoding' => 'UTF-8', 'exceptions' => true, 'connection_timeout' => 30, 'stream_context' => $context, 'cache_wsdl' => WSDL_CACHE_BOTH, ]); } catch (Throwable $e) { Log::error('[BarobillSoap] 클라이언트 생성 실패', [ 'url' => $wsdlUrl, 'error' => $e->getMessage(), ]); return null; } } protected function getCorpStateClient(): ?SoapClient { return $this->corpStateClient ??= $this->createSoapClient($this->soapUrls['corpstate']); } protected function getBankAccountClient(): ?SoapClient { return $this->bankAccountClient ??= $this->createSoapClient($this->soapUrls['bankaccount']); } protected function getCardClient(): ?SoapClient { return $this->cardClient ??= $this->createSoapClient($this->soapUrls['card']); } protected function getTiClient(): ?SoapClient { return $this->tiClient ??= $this->createSoapClient($this->soapUrls['ti']); } protected function getKakaotalkClient(): ?SoapClient { return $this->kakaotalkClient ??= $this->createSoapClient($this->soapUrls['kakaotalk']); } protected function getSmsClient(): ?SoapClient { return $this->smsClient ??= $this->createSoapClient($this->soapUrls['sms']); } // ========================================================================= // SOAP 호출 (핵심) // ========================================================================= /** * SOAP 메서드 호출 */ public function call(string $service, string $method, array $params = []): array { $client = match ($service) { 'corpstate' => $this->getCorpStateClient(), 'ti' => $this->getTiClient(), 'bankaccount' => $this->getBankAccountClient(), 'card' => $this->getCardClient(), 'kakaotalk' => $this->getKakaotalkClient(), 'sms' => $this->getSmsClient(), default => null, }; if (! $client) { return [ 'success' => false, 'error' => "SOAP 클라이언트 초기화 실패 ({$service})", 'error_code' => -1, ]; } if (empty($this->certKey)) { return [ 'success' => false, 'error' => 'CERTKEY가 설정되지 않았습니다.', 'error_code' => -2, ]; } if (! isset($params['CERTKEY'])) { $params['CERTKEY'] = $this->certKey; } try { $startTime = microtime(true); $result = $client->$method($params); $resultProperty = $method.'Result'; $elapsed = round((microtime(true) - $startTime) * 1000); Log::debug("[BarobillSoap] {$method} 완료 ({$elapsed}ms)"); if (isset($result->$resultProperty)) { $resultData = $result->$resultProperty; if (is_numeric($resultData) && $resultData < 0) { $errorMessage = $this->errorMessages[(int) $resultData] ?? "바로빌 API 오류 코드: {$resultData}"; Log::error('[BarobillSoap] API 오류', [ 'method' => $method, 'error_code' => $resultData, 'error_message' => $errorMessage, ]); return [ 'success' => false, 'error' => $errorMessage, 'error_code' => (int) $resultData, 'data' => $resultData, ]; } return ['success' => true, 'data' => $resultData]; } return ['success' => true, 'data' => $result]; } catch (SoapFault $e) { Log::error('[BarobillSoap] SOAP 오류', [ 'method' => $method, 'fault' => $e->getMessage(), ]); return [ 'success' => false, 'error' => 'SOAP 오류: '.$e->getMessage(), 'error_code' => $e->getCode(), ]; } catch (Throwable $e) { Log::error('[BarobillSoap] 호출 오류', [ 'method' => $method, 'error' => $e->getMessage(), ]); return [ 'success' => false, 'error' => 'API 호출 오류: '.$e->getMessage(), 'error_code' => -999, ]; } } // ========================================================================= // 회원관리 (CORPSTATE) // ========================================================================= /** * 회원사 등록 */ public function registCorp(array $data): array { $params = [ 'CorpNum' => $this->formatBizNo($data['biz_no']), 'CorpName' => $data['corp_name'], 'CEOName' => $data['ceo_name'], 'BizType' => $data['biz_type'] ?? '', 'BizClass' => $data['biz_class'] ?? '', 'PostNum' => $data['post_num'] ?? '', 'Addr1' => $data['addr'] ?? '', 'Addr2' => '', 'MemberName' => $data['manager_name'] ?? '', 'JuminNum' => '', 'ID' => $data['barobill_id'], 'PWD' => $data['barobill_pwd'], 'Grade' => '2', 'TEL' => $data['tel'] ?? '', 'HP' => $data['manager_hp'] ?? '', 'Email' => $data['manager_email'] ?? '', ]; return $this->call('corpstate', 'RegistCorp', $params); } /** * 회원사 정보 수정 */ public function updateCorpInfo(array $data): array { $params = [ 'CorpNum' => $this->formatBizNo($data['biz_no']), 'CorpName' => $data['corp_name'], 'CEOName' => $data['ceo_name'], 'BizType' => $data['biz_type'] ?? '', 'BizClass' => $data['biz_class'] ?? '', 'PostNum' => $data['post_num'] ?? '', 'Addr1' => $data['addr'] ?? '', 'Addr2' => '', 'MemberName' => $data['manager_name'] ?? '', 'TEL' => $data['tel'] ?? '', 'HP' => $data['manager_hp'] ?? '', 'Email' => $data['manager_email'] ?? '', ]; return $this->call('corpstate', 'UpdateCorpInfo', $params); } /** * 회원사 상태 조회 */ public function getCorpState(string $corpNum): array { return $this->call('corpstate', 'GetCorpState', [ 'CorpNum' => $this->formatBizNo($corpNum), ]); } // ========================================================================= // 계좌조회 (BANKACCOUNT) // ========================================================================= /** * 등록계좌 목록 조회 */ public function getBankAccounts(string $corpNum, bool $availOnly = true): array { return $this->call('bankaccount', 'GetBankAccountEx', [ 'CorpNum' => $this->formatBizNo($corpNum), 'AvailOnly' => $availOnly ? 1 : 0, ]); } /** * 계좌 기간별 입출금내역 조회 */ public function getPeriodBankAccountTransLog( string $corpNum, string $id, string $bankAccountNum, string $startDate, string $endDate, int $countPerPage = 1000, int $currentPage = 1 ): array { return $this->call('bankaccount', 'GetPeriodBankAccountTransLog', [ 'CorpNum' => $this->formatBizNo($corpNum), 'ID' => $id, 'BankAccountNum' => $bankAccountNum, 'StartDate' => $startDate, 'EndDate' => $endDate, 'TransDirection' => 1, 'CountPerPage' => $countPerPage, 'CurrentPage' => $currentPage, 'OrderDirection' => 2, ]); } /** * 계좌조회 신청 URL 조회 */ public function getBankAccountScrapRequestUrl(string $corpNum, string $userId, string $userPwd): array { return $this->call('bankaccount', 'GetBankAccountScrapRequestURL', [ 'CorpNum' => $this->formatBizNo($corpNum), 'ID' => $userId, 'PWD' => $userPwd, ]); } /** * 인증서 등록 URL 조회 */ public function getCertificateRegistUrl(string $corpNum, string $userId, string $userPwd): array { return $this->call('bankaccount', 'GetCertificateRegistURL', [ 'CorpNum' => $this->formatBizNo($corpNum), 'ID' => $userId, 'PWD' => $userPwd, ]); } /** * 인증서 유효성 확인 */ public function checkCertificateValid(string $corpNum): array { return $this->call('bankaccount', 'CheckCERTIsValid', [ 'CorpNum' => $this->formatBizNo($corpNum), ]); } /** * 인증서 만료일 조회 */ public function getCertificateExpireDate(string $corpNum): array { return $this->call('bankaccount', 'GetCertificateExpireDate', [ 'CorpNum' => $this->formatBizNo($corpNum), ]); } /** * 인증서 등록일 조회 */ public function getCertificateRegistDate(string $corpNum): array { return $this->call('bankaccount', 'GetCertificateRegistDate', [ 'CorpNum' => $this->formatBizNo($corpNum), ]); } /** * 충전잔액 조회 */ public function getBalanceCostAmount(string $corpNum): array { return $this->call('bankaccount', 'GetBalanceCostAmountEx', [ 'CorpNum' => $this->formatBizNo($corpNum), ]); } /** * 현금충전 URL 조회 */ public function getCashChargeUrl(string $corpNum, string $userId, string $userPwd): array { return $this->call('bankaccount', 'GetCashChargeURL', [ 'CorpNum' => $this->formatBizNo($corpNum), 'ID' => $userId, 'PWD' => $userPwd, ]); } /** * 계좌 관리 URL 조회 */ public function getBankAccountManagementUrl(string $corpNum, string $userId, string $userPwd): array { return $this->call('bankaccount', 'GetBankAccountManagementURL', [ 'CorpNum' => $this->formatBizNo($corpNum), 'ID' => $userId, 'PWD' => $userPwd, ]); } /** * 입출금내역 조회 URL */ public function getBankAccountLogUrl(string $corpNum, string $userId, string $userPwd): array { return $this->call('bankaccount', 'GetBankAccountLogURL', [ 'CorpNum' => $this->formatBizNo($corpNum), 'ID' => $userId, 'PWD' => $userPwd, ]); } /** * 바로빌 범용 URL 조회 */ public function getBarobillUrl(string $corpNum, string $userId, string $userPwd, string $togo = ''): array { return $this->call('bankaccount', 'GetBaroBillURL', [ 'CorpNum' => $this->formatBizNo($corpNum), 'ID' => $userId, 'PWD' => $userPwd, 'TOGO' => $togo, ]); } /** * 계좌 일별 입출금내역 조회 */ public function getDailyBankAccountTransLog( string $corpNum, string $id, string $bankAccountNum, string $baseDate, string $transDirection = '', int $countPerPage = 20, int $currentPage = 1 ): array { return $this->call('bankaccount', 'GetDailyBankAccountTransLog', [ 'CorpNum' => $this->formatBizNo($corpNum), 'ID' => $id, 'BankAccountNum' => $bankAccountNum, 'BaseDate' => $baseDate, 'TransDirection' => $transDirection, 'CountPerPage' => $countPerPage, 'CurrentPage' => $currentPage, 'OrderDirection' => 'D', ]); } /** * 계좌 월별 입출금내역 조회 */ public function getMonthlyBankAccountTransLog( string $corpNum, string $id, string $bankAccountNum, string $baseMonth, string $transDirection = '', int $countPerPage = 20, int $currentPage = 1 ): array { return $this->call('bankaccount', 'GetMonthlyBankAccountTransLog', [ 'CorpNum' => $this->formatBizNo($corpNum), 'ID' => $id, 'BankAccountNum' => $bankAccountNum, 'BaseMonth' => $baseMonth, 'TransDirection' => $transDirection, 'CountPerPage' => $countPerPage, 'CurrentPage' => $currentPage, 'OrderDirection' => 'D', ]); } // ========================================================================= // 카드조회 (CARD) // ========================================================================= /** * 등록카드 목록 조회 */ public function getCards(string $corpNum, bool $availOnly = true): array { return $this->call('card', 'GetCardEx2', [ 'CorpNum' => $this->formatBizNo($corpNum), 'AvailOnly' => $availOnly ? 1 : 0, ]); } /** * 카드 등록 */ public function registCard(string $corpNum, array $cardData): array { return $this->call('card', 'RegistCardEx', [ 'CorpNum' => $this->formatBizNo($corpNum), 'CardCompany' => $cardData['card_company'] ?? '', 'CardType' => $cardData['card_type'] ?? '1', 'CardNum' => preg_replace('/[^0-9]/', '', $cardData['card_num'] ?? ''), 'WebId' => $cardData['web_id'] ?? '', 'WebPwd' => $cardData['web_pwd'] ?? '', 'Alias' => $cardData['alias'] ?? '', 'Usage' => $cardData['usage'] ?? '', 'CollectCycle' => $cardData['collect_cycle'] ?? '1', ]); } /** * 카드 기간별 사용내역 조회 */ public function getPeriodCardLog( string $corpNum, string $id, string $cardNum, string $startDate, string $endDate, int $countPerPage = 1000, int $currentPage = 1 ): array { return $this->call('card', 'GetPeriodCardLog', [ 'CorpNum' => $this->formatBizNo($corpNum), 'ID' => $id, 'CardNum' => preg_replace('/[^0-9]/', '', $cardNum), 'StartDate' => $startDate, 'EndDate' => $endDate, 'CountPerPage' => $countPerPage, 'CurrentPage' => $currentPage, 'OrderDirection' => 'D', ]); } /** * 카드 등록 신청 URL 조회 */ public function getCardScrapRequestUrl(string $corpNum, string $userId, string $userPwd): array { return $this->call('card', 'GetCardScrapRequestURL', [ 'CorpNum' => $this->formatBizNo($corpNum), 'ID' => $userId, 'PWD' => $userPwd, ]); } /** * 카드 관리 URL 조회 */ public function getCardManagementUrl(string $corpNum, string $userId, string $userPwd): array { return $this->call('card', 'GetCardManagementURL', [ 'CorpNum' => $this->formatBizNo($corpNum), 'ID' => $userId, 'PWD' => $userPwd, ]); } /** * 카드 사용내역 URL 조회 */ public function getCardLogUrl(string $corpNum, string $userId, string $userPwd): array { return $this->call('card', 'GetCardLogURL', [ 'CorpNum' => $this->formatBizNo($corpNum), 'ID' => $userId, 'PWD' => $userPwd, ]); } /** * 카드 정보 수정 */ public function updateCard(string $corpNum, array $cardData): array { return $this->call('card', 'UpdateCard', [ 'CorpNum' => $this->formatBizNo($corpNum), 'CardNum' => preg_replace('/[^0-9]/', '', $cardData['card_num'] ?? ''), 'WebId' => $cardData['web_id'] ?? '', 'WebPwd' => $cardData['web_pwd'] ?? '', 'Alias' => $cardData['alias'] ?? '', 'Usage' => $cardData['usage'] ?? '', ]); } /** * 카드 해지 */ public function stopCard(string $corpNum, string $cardNum): array { return $this->call('card', 'StopCard', [ 'CorpNum' => $this->formatBizNo($corpNum), 'CardNum' => preg_replace('/[^0-9]/', '', $cardNum), ]); } /** * 카드 해지 취소 */ public function cancelStopCard(string $corpNum, string $cardNum): array { return $this->call('card', 'CancelStopCard', [ 'CorpNum' => $this->formatBizNo($corpNum), 'CardNum' => preg_replace('/[^0-9]/', '', $cardNum), ]); } /** * 카드 일별 사용내역 조회 */ public function getDailyCardLog( string $corpNum, string $id, string $cardNum, string $baseDate, int $countPerPage = 20, int $currentPage = 1 ): array { return $this->call('card', 'GetDailyCardLog', [ 'CorpNum' => $this->formatBizNo($corpNum), 'ID' => $id, 'CardNum' => preg_replace('/[^0-9]/', '', $cardNum), 'BaseDate' => $baseDate, 'CountPerPage' => $countPerPage, 'CurrentPage' => $currentPage, 'OrderDirection' => 'D', ]); } /** * 카드 월별 사용내역 조회 */ public function getMonthlyCardLog( string $corpNum, string $id, string $cardNum, string $baseMonth, int $countPerPage = 20, int $currentPage = 1 ): array { return $this->call('card', 'GetMonthlyCardLog', [ 'CorpNum' => $this->formatBizNo($corpNum), 'ID' => $id, 'CardNum' => preg_replace('/[^0-9]/', '', $cardNum), 'BaseMonth' => $baseMonth, 'CountPerPage' => $countPerPage, 'CurrentPage' => $currentPage, 'OrderDirection' => 'D', ]); } // ========================================================================= // 홈택스 (TI) // ========================================================================= /** * 홈택스 매입/매출 URL 조회 */ public function getHomeTaxUrl(string $corpNum, string $userId, string $userPwd): array { return $this->call('ti', 'GetHomeTaxURL', [ 'CorpNum' => $this->formatBizNo($corpNum), 'ID' => $userId, 'PWD' => $userPwd, ]); } /** * 세금계산서 발행 URL 조회 */ public function getTaxInvoiceIssueUrl(string $corpNum, string $userId, string $userPwd): array { return $this->call('ti', 'GetTaxInvoiceIssueURL', [ 'CorpNum' => $this->formatBizNo($corpNum), 'ID' => $userId, 'PWD' => $userPwd, ]); } /** * 세금계산서 목록 URL 조회 */ public function getTaxInvoiceListUrl(string $corpNum, string $userId, string $userPwd): array { return $this->call('ti', 'GetTaxInvoiceListURL', [ 'CorpNum' => $this->formatBizNo($corpNum), 'ID' => $userId, 'PWD' => $userPwd, ]); } // ========================================================================= // 카카오톡 (KAKAOTALK) // ========================================================================= /** * 카카오톡 채널 목록 조회 */ public function getKakaotalkChannels(string $corpNum): array { return $this->call('kakaotalk', 'GetKakaotalkChannels', [ 'CorpNum' => $this->formatBizNo($corpNum), ]); } /** * 카카오톡 채널 관리 URL 조회 */ public function getKakaotalkChannelManagementUrl(string $corpNum, string $id): array { return $this->call('kakaotalk', 'GetKakaotalkChannelManagementURL', [ 'CorpNum' => $this->formatBizNo($corpNum), 'ID' => $id, ]); } /** * 카카오톡 템플릿 목록 조회 */ public function getKakaotalkTemplates(string $corpNum, string $channelId): array { return $this->call('kakaotalk', 'GetKakaotalkTemplates', [ 'CorpNum' => $this->formatBizNo($corpNum), 'ChannelId' => $channelId, ]); } /** * 카카오톡 템플릿 관리 URL 조회 */ public function getKakaotalkTemplateManagementUrl(string $corpNum, string $id): array { return $this->call('kakaotalk', 'GetKakaotalkTemplateManagementURL', [ 'CorpNum' => $this->formatBizNo($corpNum), 'ID' => $id, ]); } /** * 알림톡 단건 발송 */ public function sendATKakaotalk( string $corpNum, string $senderId, string $yellowId, string $templateName, string $receiverName, string $receiverNum, string $title, string $message, string $smsMessage = '', string $smsSubject = '', string $smsSenderNum = '', string $reserveDT = '' ): array { return $this->call('kakaotalk', 'SendATKakaotalk', [ 'CorpNum' => $this->formatBizNo($corpNum), 'SenderID' => $senderId, 'YellowId' => $yellowId, 'TemplateName' => $templateName, 'SendDT' => $reserveDT, 'SmsReply' => (empty($smsMessage) || empty($smsSenderNum)) ? 'N' : 'S', 'SmsSenderNum' => $smsSenderNum, 'KakaotalkMessage' => [ 'ReceiverName' => $receiverName, 'ReceiverNum' => $receiverNum, 'Title' => $title, 'Message' => $message, 'SmsMessage' => $smsMessage, 'SmsSubject' => $smsSubject, ], ]); } /** * 알림톡 단건 발송 (버튼 포함) */ public function sendATKakaotalkEx( string $corpNum, string $senderId, string $yellowId, string $templateName, string $receiverName, string $receiverNum, string $title, string $message, array $buttons = [], string $smsMessage = '', string $smsSubject = '', string $smsSenderNum = '', string $reserveDT = '' ): array { $kakaotalkMessage = [ 'ReceiverName' => $receiverName, 'ReceiverNum' => $receiverNum, 'Title' => $title, 'Message' => $message, 'SmsMessage' => $smsMessage, 'SmsSubject' => $smsSubject, ]; if (! empty($buttons)) { $kakaotalkMessage['Buttons'] = ['KakaotalkButton' => $buttons]; } return $this->call('kakaotalk', 'SendATKakaotalkEx', [ 'CorpNum' => $this->formatBizNo($corpNum), 'SenderID' => $senderId, 'YellowId' => $yellowId, 'TemplateName' => $templateName, 'SendDT' => $reserveDT, 'SmsReply' => (empty($smsMessage) || empty($smsSenderNum)) ? 'N' : 'S', 'SmsSenderNum' => $smsSenderNum, 'KakaotalkMessage' => $kakaotalkMessage, ]); } /** * 알림톡 대량 발송 */ public function sendATKakaotalks( string $corpNum, string $senderId, string $yellowId, string $templateName, array $messages, string $reserveDT = '' ): array { return $this->call('kakaotalk', 'SendATKakaotalks', [ 'CorpNum' => $this->formatBizNo($corpNum), 'SenderID' => $senderId, 'YellowId' => $yellowId, 'TemplateName' => $templateName, 'SendDT' => $reserveDT, 'SmsReply' => 'N', 'SmsSenderNum' => '', 'KakaotalkMessages' => ['KakaotalkATMessage' => $messages], ]); } /** * 친구톡 텍스트 단건 발송 */ public function sendFTKakaotalk( string $corpNum, string $senderId, string $channelId, string $receiverName, string $receiverNum, string $message, array $buttons = [], string $smsMessage = '', string $smsSubject = '', bool $adYn = false, string $reserveDT = '' ): array { return $this->call('kakaotalk', 'SendFTKakaotalk', [ 'CorpNum' => $this->formatBizNo($corpNum), 'SenderID' => $senderId, 'ChannelId' => $channelId, 'ReceiverName' => $receiverName, 'ReceiverNum' => $receiverNum, 'Message' => $message, 'Buttons' => $buttons, 'SmsMessage' => $smsMessage, 'SmsSubject' => $smsSubject, 'AdYn' => $adYn ? 'Y' : 'N', 'ReserveDT' => $reserveDT, ]); } /** * 친구톡 대량 발송 */ public function sendFTKakaotalks( string $corpNum, string $senderId, string $channelId, array $messages, bool $adYn = false, string $reserveDT = '' ): array { return $this->call('kakaotalk', 'SendFTKakaotalks', [ 'CorpNum' => $this->formatBizNo($corpNum), 'SenderID' => $senderId, 'ChannelId' => $channelId, 'Messages' => $messages, 'AdYn' => $adYn ? 'Y' : 'N', 'ReserveDT' => $reserveDT, ]); } /** * 친구톡 이미지 발송 */ public function sendFIKakaotalk( string $corpNum, string $senderId, string $channelId, string $receiverName, string $receiverNum, string $message, string $imageUrl, array $buttons = [], string $smsMessage = '', string $smsSubject = '', bool $adYn = false, string $reserveDT = '' ): array { return $this->call('kakaotalk', 'SendFIKakaotalk', [ 'CorpNum' => $this->formatBizNo($corpNum), 'SenderID' => $senderId, 'ChannelId' => $channelId, 'ReceiverName' => $receiverName, 'ReceiverNum' => $receiverNum, 'Message' => $message, 'ImageURL' => $imageUrl, 'Buttons' => $buttons, 'SmsMessage' => $smsMessage, 'SmsSubject' => $smsSubject, 'AdYn' => $adYn ? 'Y' : 'N', 'ReserveDT' => $reserveDT, ]); } /** * 친구톡 와이드 이미지 발송 */ public function sendFWKakaotalk( string $corpNum, string $senderId, string $channelId, string $receiverName, string $receiverNum, string $message, string $imageUrl, array $buttons = [], string $smsMessage = '', string $smsSubject = '', bool $adYn = false, string $reserveDT = '' ): array { return $this->call('kakaotalk', 'SendFWKakaotalk', [ 'CorpNum' => $this->formatBizNo($corpNum), 'SenderID' => $senderId, 'ChannelId' => $channelId, 'ReceiverName' => $receiverName, 'ReceiverNum' => $receiverNum, 'Message' => $message, 'ImageURL' => $imageUrl, 'Buttons' => $buttons, 'SmsMessage' => $smsMessage, 'SmsSubject' => $smsSubject, 'AdYn' => $adYn ? 'Y' : 'N', 'ReserveDT' => $reserveDT, ]); } /** * 카카오톡 전송 결과 조회 (단건) */ public function getSendKakaotalk(string $corpNum, string $sendKey): array { return $this->call('kakaotalk', 'GetSendKakaotalk', [ 'CorpNum' => $this->formatBizNo($corpNum), 'SendKey' => $sendKey, ]); } /** * 카카오톡 전송 결과 조회 (다건) */ public function getSendKakaotalks(string $corpNum, array $sendKeyList): array { return $this->call('kakaotalk', 'GetSendKakaotalks', [ 'CorpNum' => $this->formatBizNo($corpNum), 'SendKeyList' => $sendKeyList, ]); } /** * 카카오톡 예약 전송 취소 */ public function cancelReservedKakaotalk(string $corpNum, string $sendKey): array { return $this->call('kakaotalk', 'CancelReservedKakaotalk', [ 'CorpNum' => $this->formatBizNo($corpNum), 'SendKey' => $sendKey, ]); } // ========================================================================= // 문자 (SMS) // ========================================================================= /** * SMS 단문 발송 */ public function sendSMSMessage( string $corpNum, string $senderId, string $fromNumber, string $toName, string $toNumber, string $contents, string $sendDT = '', string $refKey = '' ): array { return $this->call('sms', 'SendSMSMessage', [ 'CorpNum' => $this->formatBizNo($corpNum), 'SenderID' => $senderId, 'FromNumber' => $fromNumber, 'ToName' => $toName, 'ToNumber' => $toNumber, 'Contents' => $contents, 'SendDT' => $sendDT, 'RefKey' => $refKey, ]); } /** * SMS 발신번호 등록 여부 확인 */ public function checkSMSFromNumber(string $corpNum, string $fromNumber): array { return $this->call('sms', 'CheckSMSFromNumber', [ 'CorpNum' => $this->formatBizNo($corpNum), 'FromNumber' => $fromNumber, ]); } /** * SMS 등록된 발신번호 목록 */ public function getSMSFromNumbers(string $corpNum): array { return $this->call('sms', 'GetSMSFromNumbers', [ 'CorpNum' => $this->formatBizNo($corpNum), ]); } /** * SMS 전송 상태 조회 */ public function getSMSSendState(string $corpNum, string $sendKey): array { return $this->call('sms', 'GetSMSSendState', [ 'CorpNum' => $this->formatBizNo($corpNum), 'SendKey' => $sendKey, ]); } // ========================================================================= // 유틸리티 // ========================================================================= protected function formatBizNo(string $bizNo): string { return preg_replace('/[^0-9]/', '', $bizNo); } /** * 은행 코드 목록 */ public static array $bankCodes = [ '02' => '산업은행', '03' => '기업은행', '04' => '국민은행', '07' => '수협은행', '11' => 'NH농협은행', '20' => '우리은행', '23' => '제일은행(SC)', '26' => '신한은행', '27' => '한국씨티은행', '31' => '대구은행', '32' => '부산은행', '34' => '광주은행', '35' => '제주은행', '37' => '전북은행', '39' => '경남은행', '45' => '새마을금고연합', '48' => '신협', '71' => '우체국', '81' => 'KEB하나은행', '88' => '신한은행(통합)', '89' => '케이뱅크', '90' => '카카오뱅크', '92' => '토스뱅크', ]; /** * 카드사 코드 목록 */ public static array $cardCompanyCodes = [ '01' => '비씨카드', '02' => '국민카드', '04' => '삼성카드', '05' => '현대카드', '06' => '롯데카드', '07' => '신한카드', '08' => '하나카드', '09' => '우리카드', '10' => 'NH농협카드', '11' => '씨티카드', ]; }