From 394dd258cdc454fc93283c1807dab3cce7c7e02d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=B4=EA=B3=A4?= Date: Thu, 26 Feb 2026 10:20:35 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20[barobill]=20=EB=8F=85=EB=A6=BD=20SMS?= =?UTF-8?q?=20API=20=EC=97=B0=EB=8F=99=20=EB=B0=8F=20OTP=20=EB=B0=9C?= =?UTF-8?q?=EC=86=A1=20=EC=A0=84=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - BarobillService에 SMS WSDL 엔드포인트 추가 - sendSMSMessage, checkSMSFromNumber, getSMSFromNumbers 메서드 추가 - sendOtpViaSms를 알림톡 대체발송 → 독립 SMS API(SendSMSMessage)로 전환 --- .../ESign/EsignPublicController.php | 30 ++--- app/Services/Barobill/BarobillService.php | 121 ++++++++++++++++++ 2 files changed, 129 insertions(+), 22 deletions(-) diff --git a/app/Http/Controllers/ESign/EsignPublicController.php b/app/Http/Controllers/ESign/EsignPublicController.php index 4e3bcbe0..f5b803ba 100644 --- a/app/Http/Controllers/ESign/EsignPublicController.php +++ b/app/Http/Controllers/ESign/EsignPublicController.php @@ -614,7 +614,7 @@ public function downloadDocument(string $token): StreamedResponse|JsonResponse // ─── Private ─── /** - * SMS로 OTP 발송 (바로빌 알림톡 SMS 대체발송 기능 활용) + * SMS로 OTP 발송 (바로빌 독립 SMS API 사용) */ private function sendOtpViaSms(EsignContract $contract, EsignSigner $signer, string $otpCode): bool { @@ -632,31 +632,17 @@ private function sendOtpViaSms(EsignContract $contract, EsignSigner $signer, str $barobill = app(BarobillService::class); $barobill->setServerMode($member->server_mode ?? 'production'); - // 채널 ID 조회 - $channelResult = $barobill->getKakaotalkChannels($member->biz_no); - $yellowId = ''; - if ($channelResult['success'] ?? false) { - $chData = $channelResult['data']; - if (is_object($chData) && isset($chData->KakaotalkChannel)) { - $ch = is_array($chData->KakaotalkChannel) ? $chData->KakaotalkChannel[0] : $chData->KakaotalkChannel; - $yellowId = $ch->ChannelId ?? ''; - } - } - + $fromNumber = preg_replace('/[^0-9]/', '', $member->manager_hp); + $toNumber = preg_replace('/[^0-9]/', '', $signer->phone); $smsText = "[SAM] 전자계약 인증코드: {$otpCode} (5분 이내 입력)"; - $result = $barobill->sendATKakaotalkEx( + $result = $barobill->sendSMSMessage( corpNum: $member->biz_no, senderId: $member->barobill_id, - yellowId: $yellowId, - templateName: '인증코드', - receiverName: $signer->name, - receiverNum: preg_replace('/[^0-9]/', '', $signer->phone), - title: '', - message: $smsText, - buttons: [], - smsMessage: $smsText, - smsSenderNum: preg_replace('/[^0-9]/', '', $member->manager_hp), + fromNumber: $fromNumber, + toName: $signer->name, + toNumber: $toNumber, + contents: $smsText, ); if ($result['success'] ?? false) { diff --git a/app/Services/Barobill/BarobillService.php b/app/Services/Barobill/BarobillService.php index e2415126..e2250016 100644 --- a/app/Services/Barobill/BarobillService.php +++ b/app/Services/Barobill/BarobillService.php @@ -47,6 +47,11 @@ class BarobillService */ protected ?SoapClient $kakaotalkClient = null; + /** + * SOAP 클라이언트 (문자전송용 - SMS) + */ + protected ?SoapClient $smsClient = null; + /** * CERTKEY (인증키) */ @@ -175,6 +180,7 @@ protected function initializeConfig(): void 'bankaccount' => $baseUrl.'/BANKACCOUNT.asmx?WSDL', 'card' => $baseUrl.'/CARD.asmx?WSDL', 'kakaotalk' => $baseUrl.'/KAKAOTALK.asmx?WSDL', + 'sms' => $baseUrl.'/SMS.asmx?WSDL', ]; } } @@ -207,6 +213,7 @@ protected function buildSoapUrls(string $baseUrl): array 'bankaccount' => $baseUrl.'/BANKACCOUNT.asmx?WSDL', 'card' => $baseUrl.'/CARD.asmx?WSDL', 'kakaotalk' => $baseUrl.'/KAKAOTALK.asmx?WSDL', + 'sms' => $baseUrl.'/SMS.asmx?WSDL', ]; } @@ -329,6 +336,7 @@ protected function call(string $service, string $method, array $params = []): ar 'bankaccount' => $this->getBankAccountClient(), 'card' => $this->getCardClient(), 'kakaotalk' => $this->getKakaotalkClient(), + 'sms' => $this->getSmsClient(), default => null, }; @@ -1637,4 +1645,117 @@ public function cancelReservedKakaotalk(string $corpNum, string $sendKey): array return $this->call('kakaotalk', 'CancelReservedKakaotalk', $params); } + + // ======================================== + // 문자 서비스 (SMS) + // ======================================== + + /** + * SMS SOAP 클라이언트 가져오기 + */ + protected function getSmsClient(): ?SoapClient + { + if ($this->smsClient === null) { + try { + $this->smsClient = new SoapClient($this->soapUrls['sms'], [ + 'trace' => true, + 'encoding' => 'UTF-8', + 'exceptions' => true, + 'connection_timeout' => 30, + 'cache_wsdl' => WSDL_CACHE_NONE, + ]); + } catch (Throwable $e) { + Log::error('바로빌 SMS SOAP 클라이언트 생성 실패', [ + 'error' => $e->getMessage(), + 'url' => $this->soapUrls['sms'], + ]); + + return null; + } + } + + return $this->smsClient; + } + + /** + * SMS 단문 발송 + * + * @param string $corpNum 회원사 사업자번호 + * @param string $senderId 바로빌 계정 ID + * @param string $fromNumber 발신번호 + * @param string $toName 수신자명 + * @param string $toNumber 수신 전화번호 + * @param string $contents 메시지 내용 (90바이트 이내) + * @param string $sendDT 예약일시 (빈값 = 즉시발송) + * @param string $refKey 참조키 + */ + public function sendSMSMessage( + string $corpNum, + string $senderId, + string $fromNumber, + string $toName, + string $toNumber, + string $contents, + string $sendDT = '', + string $refKey = '' + ): array { + $params = [ + 'CorpNum' => $this->formatBizNo($corpNum), + 'SenderID' => $senderId, + 'FromNumber' => $fromNumber, + 'ToName' => $toName, + 'ToNumber' => $toNumber, + 'Contents' => $contents, + 'SendDT' => $sendDT, + 'RefKey' => $refKey, + ]; + + return $this->call('sms', 'SendSMSMessage', $params); + } + + /** + * 발신번호 등록 여부 확인 + * + * @param string $corpNum 회원사 사업자번호 + * @param string $fromNumber 확인할 발신번호 + */ + public function checkSMSFromNumber(string $corpNum, string $fromNumber): array + { + $params = [ + 'CorpNum' => $this->formatBizNo($corpNum), + 'FromNumber' => $fromNumber, + ]; + + return $this->call('sms', 'CheckSMSFromNumber', $params); + } + + /** + * 등록된 발신번호 목록 조회 + * + * @param string $corpNum 회원사 사업자번호 + */ + public function getSMSFromNumbers(string $corpNum): array + { + $params = [ + 'CorpNum' => $this->formatBizNo($corpNum), + ]; + + return $this->call('sms', 'GetSMSFromNumbers', $params); + } + + /** + * SMS 전송 상태 조회 + * + * @param string $corpNum 회원사 사업자번호 + * @param string $sendKey 전송키 + */ + public function getSMSSendState(string $corpNum, string $sendKey): array + { + $params = [ + 'CorpNum' => $this->formatBizNo($corpNum), + 'SendKey' => $sendKey, + ]; + + return $this->call('sms', 'GetSMSSendState', $params); + } }