> For the complete documentation index, see [llms.txt](https://tech.x2bee.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://tech.x2bee.com/dev-guide/dev-start/undefined/undefined-2.md).

# 알림톡 발송

이 문서는 알림톡전송 소스와 방법에 대해 다룹니다.

첫 번째로는 Config 설정 방법 및 확인에 대해 설명합니다.\
두 번째로 각 업무단 작성 방법을 설명합니다.

{% hint style="info" %}
**\<update>**

2023.08.03

* failover 관련 가이드가 추가되었습니다.
* 알림톡 전송시 Api Common을 호출을 지향합니다.
  {% endhint %}

***

## Config 설정

**application.yml 예시:**

```yaml
spring:
  bizMessage:
    accessKey: VHIZ4hLLrhf6uyRIrk4F
    secretKey: pHvcggk52DXYOYYUDvXyLi5RkcmwneeMoOx8xoTd
    alimTalk:
      plusFriendId: "@X2BEE"
      serviceId: ncp:kkobizmsg:kr:3094856:x2bee
```

필수 속성

* <kbd>accessKey</kbd>
* <kbd>secretKey</kbd>
* <kbd>alimTalk.plusFriendId</kbd>
* <kbd>alimTalk.serviceId</kbd>

위 속성들은 NCP(Naver Cloud Platform) 에서 발급받아 작성합니다.

## Sample 소스 및 설명

* 프로젝트 예시: <https://gitlab.x2bee.com/x2bee-venus-beta/venus-x2bee-api-sample-vanilla>

**BizMessageController** 예시 (요약):

```java
... 
private final MessageSender messageSender;

/* 알림톡 샘플 */
@PostMapping("/alimTalk")
public ResponseEntity<Response> bizMessage() throws Exception {
    ...
    String templateCode = "PO2B";
    String template = "[#{coNm}] 배송시작 안내\n" +
                      "\n" +
                      "#{mbrNm} 고객님께서 주문하신 상품의 배송이 곧 시작됩니다.\n" +
                      "\n" +
                      "■ 주문상품 정보\n" +
                      "- 주문번호 : #{orderNo}\n" +
                      "- 상품명 : #{goodsNm}\n" +
                      "\n" +
                      "※ 고객센터 #{ccNo}(유료)"; // Template 문구 -> 변수명 처리로 변경됨.

    // SendParams params = 임시객체 (비즈니스 로직 VO 사용 권장)
    SendParams params = SendParams.builder()
        .coNm("X2BEE")
        .mbrNm("김플래")
        .orderNo("O0000000001")
        .goodsNm("양말 외 1건")
        .ccNo("02-3333-4444")
        .build();

    template = messageSender.replaceTemplateFormat(template, params);

    List<Buttons> buttons = new ArrayList<>();
    // 버튼 추가
    buttons.add(Buttons.builder()
        .linkPc("https://plateer.com")      // https:// 포함, 필수
        .linkMobile("https://plateer.com")  // https:// 포함, 필수
        .name("주문상세 보기")               // 템플릿 버튼 명과 정확히 일치해야 함
        .type("WL")                         // 템플릿 버튼 타입과 정확히 일치해야 함. 기본 WL
        .build());

    for (int i = 0; i < 1; i++) {
        messagesList.add(MessagesRequest.builder()
            .receiverPhoneNumber("01012341234")
            .content(template)
            .buttons(buttons)
            .build());
    }

    //======================================================
    // API-COMMON 에서 직접 호출시
    BizMessageResponse str = messageSender.sendAlimTalk(messagesList, templateCode);
    //======================================================

    // API-COMMON 호출시
    BizMessageRequest request = BizMessageRequest.builder()
        .messages(messagesList)     // 필수
        .templateCode(templateCode) // 필수
        .build();

    BizMessageResponse response = restApiUtil.post(
        this.commonApiUrl + "/api/common/interface/bizmessage/sendalimtalk",
        request,
        new ParameterizedTypeReference<Response<BizMessageResponse>>() {}
    ).getPayload();

    ...
}
...
```

* (1), (2), (7), (8) 은 아래 표를 참조하여 작성합니다.
* <mark style="color:red;">(2), (7), (8) 의 경우 Naver Cloud Platform 에서 승인받은 템플릿 내용과 버튼 명, 버튼 타입이 정확하게 일치해야 합니다.</mark>
* <kbd><mark style="color:red;">템플릿 내용 컬럼<mark style="color:red;"></kbd><mark style="color:red;">과 버튼 컬럼의</mark> <mark style="color:red;"></mark><kbd><mark style="color:red;">type<mark style="color:red;"></kbd><mark style="color:red;">과</mark> <mark style="color:red;"></mark><kbd><mark style="color:red;">name<mark style="color:red;"></kbd><mark style="color:red;">을 참조하십시오.</mark>

{% hint style="info" %}
템플릿 내용의 #{...} 변수명과 비즈니스 로직 VO의 변수명이 일치하면 replaceTemplateFormat에서 치환됩니다. 예제의 SendParams 는 제공하지 않습니다.
{% endhint %}

### NCP 승인 템플릿 목록 테이블

<table><thead><tr><th width="77.888916015625"></th><th width="107">TMPL-CODE (1)</th><th width="108.111083984375">구분</th><th>템플릿 내용 (2)</th><th>버튼 (7), (8)</th></tr></thead><tbody><tr><td>1</td><td>PO1A</td><td>상품Q&#x26;A 답변 완료</td><td><pre><code>[#{고객사명}] 상품Q&#x26;A 답변완료 안내 고객님께서 문의하신 내용에 대한 답변이 완료되었습니다. ※ 고객센터 #{고객센터전화번호}(유료)
</code></pre></td><td>type : WL name : 상품Q&#x26;A 문의 답변 확인</td></tr><tr><td>2</td><td>PO2A</td><td>주문완료</td><td><pre><code>[#{고객사명}] 주문완료 안내 #{고객명} 고객님의 주문이 완료되었습니다. ■ 주문정보 - 주문번호 : #{주문번호} - 주문일 : #{주문일} - 상품명 : #{상품명외N건(수량)개} - 결제금액 : #{결제금액}원 - 배송지 : #{배송지} ※ 고객센터 #{고객센터전화번호}(유료)
</code></pre></td><td>type : WL name : 주문상세 보기</td></tr><tr><td>3</td><td>PO2B</td><td>배송시작</td><td><pre><code>[#{고객사명}] 배송시작 안내 #{고객명} 고객님께서 주문하신 상품의 배송이 곧 시작됩니다. ■ 주문상품 정보 - 주문번호 : #{주문번호} - 상품명 : #{상품명외N건(수량)개} ※ 고객센터 #{고객센터전화번호}(유료)
</code></pre></td><td>type : WL name : 주문상세 보기</td></tr><tr><td>4</td><td>PO2C</td><td>배송지연</td><td><pre><code>[#{고객사명}] 배송지연 안내 #{고객명} 고객님께서 주문하신 상품의 배송이 지연되고 있습니다. 불편을 드려 죄송합니다. 빠른시간 내 상품확보를 위해 최선을 다하겠습니다. 상품 수급이 불가하거나 장기화될 시 취소 안내를 드릴 수도 있습니다. ■ 주문상품 정보 - 주문번호 : #{주문번호} - 상품명 : #{상품명외N건(수량)개} 주문취소를 원하시는 경우, 고객센터로 연락 바랍니다. ※ 고객센터 #{고객센터전화번호}(유료)
</code></pre></td><td>type : WL name : 주문상세 보기</td></tr><tr><td>5</td><td>PO2D</td><td>주문취소</td><td><pre><code>[#{고객사명}] 주문취소 안내 고객님의 주문(#{주문번호})이 취소되었습니다. ■ 주문 취소정보 - 주문번호 : #{주문번호} - 상품명 : #{상품명외N건(수량)개} - 환불금액 : #{환불금액} ※ 고객센터 #{고객센터전화번호}(유료)
</code></pre></td><td>type : WL name : 주문상세 보기</td></tr><tr><td>6</td><td>PO2E</td><td>교환접수 (추가배송비 결제 요청)</td><td><pre><code>[#{고객사명}] 교환배송비 결제 안내 #{고객명} 고객님께서 신청하신 교환이 접수되었습니다. 마이페이지에서 추가 배송비를 결제하신 후에 교환이 시작됩니다. ■ 교환 주문정보 - 주문번호 : #{주문번호} - 상품명 : #{상품명외N건(수량)개} - 교환 옵션 : #{컬러,사이즈} → #{컬러,사이즈} - 추가 배송비: #{추가배송비} 교환 요청하신 상품은 고객사에 수거된 후, 새 상품이 출고됩니다. (상품 불량, 재고 부족 등의 이슈로 교환이 진행되지 않을 수 있는 점 양해 부탁드립니다.) 수거부터 교환 배송까지는 약 7일 정도 소요되며, 수거가 지연될 경우 고객사 고객센터로 문의 부탁드립니다. ※ 고객센터 #{고객센터전화번호}(유료)
</code></pre></td><td>type : WL name : 주문상세 보기</td></tr><tr><td>7</td><td>PO2F</td><td>교환접수</td><td><pre><code>[#{고객사명}] 교환접수 안내 #{고객명} 고객님께서 신청하신 교환이 접수되었습니다. ■ 교환 주문정보 - 주문번호 : #{주문번호} - 상품명 : #{상품명외N건(수량)개} - 교환 옵션 : #{컬러,사이즈} → #{컬러,사이즈} 교환 요청하신 상품은 고객사에 수거된 후, 새 상품이 출고됩니다. (상품 불량, 재고 부족 등의 이슈로 교환이 진행되지 않을 수 있는 점 양해 부탁드립니다.) 수거부터 교환 배송까지는 약 7일 정도 소요되며, 수거가 지연될 경우 고객사 고객센터로 문의 부탁드립니다. ※ 고객센터 #{고객센터전화번호}(유료)
</code></pre></td><td>type : WL name : 주문상세 보기</td></tr><tr><td>8</td><td>PO2G</td><td>교환 배송시작</td><td><pre><code>[#{고객사명}] 교환 배송시작 안내 #{고객명} 고객님께서 신청하신 교환 상품의 배송이 곧 시작됩니다. ■ 교환상품 정보 - 주문번호 : #{주문번호} - 상품명(수량) : #{상품명(수량)} ※ 고객센터 #{고객센터전화번호}(유료)
</code></pre></td><td>type : WL name : 주문상세 보기</td></tr><tr><td>9</td><td>PO2H</td><td>반품접수</td><td><pre><code>[#{고객사명}] 반품접수 안내 #{고객명} 고객님께서 신청하신 반품이 접수되었습니다. ■ 반품 주문정보 - 주문번호 : #{주문번호} - 상품명 : #{상품명외N건(수량)개} 반품 수거는 평일 기준 2~3일 내에 배송 받으신 택배사 기사님을 통해 수거될 예정입니다. ※ 고객센터 #{고객센터전화번호}(유료)
</code></pre></td><td>type : WL name : 주문상세 보기</td></tr><tr><td>10</td><td>PO2I</td><td>반품접수 (추가배송비 결제 요청)</td><td><pre><code>[#{고객사명}] 반품 배송비 결제 안내 #{고객명} 고객님께서 신청하신 반품이 접수되었습니다. 마이페이지에서 추가 배송비를 결제하신 후에 교환이 시작됩니다. ■ 반품 주문정보 - 주문번호 : #{주문번호} - 상품명 : #{상품명외N건(수량)개} - 추가 배송비: #{추가배송비} 반품 수거는 평일 기준 2~3일 내에 배송 받으신 택배사 기사님을 통해 수거될 예정입니다. ※ 고객센터 #{고객센터전화번호}(유료)
</code></pre></td><td>type : WL name : 주문상세 보기</td></tr><tr><td>11</td><td>PO2J</td><td>반품완료</td><td><pre><code>[#{고객사명}] 반품완료 안내 #{고객명} 고객님께서 신청하신 반품이 완료되었습니다. 반품완료일을 기준으로 카드환불은 평일 35일 후 처리되며, 정확한 날짜는 카드사별로 상이합니다. 실시간 계좌이체의 경우, 평일 12일 후(오후 6시 전후) 환불됩니다. ■ 반품정보 - 주문번호 : #{주문번호} - 상품명 : #{상품명외N건(수량)개} - 환불금액 : #{환불금액} 배송비 등 차감으로 인해 환불금액이 상이할 수 있으며, 보다 자세한 내용은 환불내역을 확인 부탁드립니다. ※ 고객센터 #{고객센터전화번호}(유료)
</code></pre></td><td>type : WL name : 주문상세 보기</td></tr><tr><td>12</td><td>PO3A</td><td>이벤트 당첨 - 경품</td><td><pre><code>[#{고객사명}] 이벤트 당첨 안내 #{고객명} 고객님, 이벤트 경품 당첨을 축하 드립니다. 당첨자 안내사항을 확인해 주세요. - 당첨된 이벤트: #{이벤트명} - 당첨 경품: #{당첨경품명} - 경품 발송일: #{경품발송일} 당첨된 경품은 이벤트 응모 시 입력한 주소지로 발송됩니다. #{경품발송일3일전날짜}까지 경품 수령지 주소를 확인/변경해 주세요. 경품 수령지 주소 변경: #{마이페이지참여내역} ※ 이 메시지는 고객님이 참여한 이벤트 당첨으로 지급된 경품 안내 메시지입니다. ※ 당첨된 경품의 제세공과금 22%는 당첨자 본인 부담입니다. ※ 고객센터 #{고객센터전화번호}(유료)
</code></pre></td><td>type : WL name : 마이페이지 참여내역</td></tr><tr><td>13</td><td>PO2K</td><td>1:1문의 답변 완료</td><td><pre><code>[#{고객사명}] 1:1 문의 답변완료 안내 #{고객명} 고객님, 문의하신 내용에 대한 답변이 완료되었습니다. 1:1문의에서 답변을 확인해주세요. ※ 고객센터 #{0000-0000}(유료)
</code></pre></td><td>type : WL name : 1:1문의 답변 확인</td></tr><tr><td>14</td><td>PO3B</td><td>휴면예정</td><td><pre><code>[#{고객사명}] 1년 이상 미로그인 회원 휴면 계정 전환 예정 안내 안녕하세요, #{고객명} 고객님 고객사명은 「개인정보보호법 제 39조 6」에 따라 최근 1년간 고객사명에 로그인하지 않으신 고객님의 개인정보를 보호하기 위해, 다음과 같이 고객님 계정 정보를 휴면 상태로 전환할 예정임을 안내드립니다. 휴면전환 계정 : #{ID} 휴면전환 예정 일자 : #{휴면전환예정일} 개인정보 보호 대상 : 회원 가입 시 입력한 개인정보와 주문 시 입력한 개인정보(이름, 성별, 생년월일, 전화번호, 이메일, 주소 등) ※ 고객사명의 다양한 혜택을 계속해서 이용하시고자 하는 경우, #{휴면전환예정일-1일}까지 고객사명에 로그인하시면 계속 이용이 가능합니다. ※ 고객센터 #{0000-0000}(유료)
</code></pre></td><td></td></tr><tr><td>15</td><td>PO3C</td><td>회원 가입</td><td><pre><code>[#{고객사명}] 회원가입완료 안내 #{고객명} 고객님, 회원 가입을 진심으로 감사드립니다. 앞으로도 많은 관심과 이용 부탁 드립니다. ※ 고객센터 #{0000-0000}(유료)
</code></pre></td><td></td></tr><tr><td>16</td><td>PO3D</td><td>마케팅 수신동의</td><td><pre><code>[#{고객사명}] 정기적 수신동의 안내 #{고객명} 고객님, 이 메시지는 정보통신망법에 따라 2년마다 발송되는 광고성 정보 수신동의 확인 메시지 입니다. 이전 수신동의일자 : #{YYYY}년 #{MM}월 #{DD}일 앞으로도 유익한 소식과 다양한 혜택으로 찾아뵙겠습니다.
</code></pre></td><td></td></tr><tr><td>17</td><td>PO3E</td><td>회원 탈퇴</td><td><pre><code>[#{고객사명}] 개인정보 파기 및 탈퇴 예정 안내 #{고객명} 고객님, 고객사명은 고객님의 탈퇴 요청에 따라 고객님의 개인정보를 보호하기 위해, 다음과 같이 개인정보 파기 및 탈퇴 처리가 진행될 예정입니다. 탈퇴 계정 : #{ID} 파기 대상 개인정보 : 이름, 성별, 생년월일, 전화번호, 이메일, 주소 등 ※ 개인정보 파기 및 탈퇴 이후에 서비스 이용을 원하시면, 신규 회원가입을 하셔야 합니다. ※ 본 메시지는 고객사명 온라인 쇼핑몰의 개인정보처리방침에 따라 발송된 메시지입니다. ※ 고객센터 #{0000-0000}(유료)
</code></pre></td><td></td></tr><tr><td>18</td><td>PO3F</td><td>임시 비밀번호 안내</td><td><pre><code>[#{고객사명}] 임시 비밀번호 안내 #{고객명}고객님의 임시 비밀번호는 [#{임시비밀번호}]입니다.
</code></pre></td><td></td></tr><tr><td>19</td><td>PO3G</td><td>관리자 인증번호 안내</td><td><pre><code>[#{고객사명}] 임시 비밀번호 안내 #{사용자명}님께서 요청하신 임시 비밀번호는 [#{인증번호}] 입니다.
</code></pre></td><td></td></tr></tbody></table>

(3) 템플릿 내용의 #{...} 과 교체할 파라미터를 비즈니스 로직에서 사용중인 VO 변수에 해당하는 변수로 set 합니다.

* <mark style="color:red;">템플릿 변수(#{…}) 명과 VO의 변수명이 일치하면 replace 됩니다.</mark>
* <mark style="color:red;">예제의 SendParams 는 제공되지 않습니다.</mark>

(4) 템플릿 내용과 파라미터 리스트를 <kbd>MessageSender</kbd>의 `replaceTemplateFormat` 메서드를 사용하여 매핑시킵니다.

(5), (6) 링크는 두개 모두 필수이며 **https\://** 를 반드시 포함해야 합니다.

(9) `x2bee-api-common-vanilla` 가 아닌 다른 프로젝트에서 알림톡을 전송하는 경우 api-common API를 호출합니다.\
예제 소스와 같이 <kbd>BizMessageRequest</kbd> 객체에 필요 파라미터들을 담아 POST 방식으로 <kbd>/api/common/interface/bizmessage/sendalimtalk</kbd> End Point를 호출합니다.

* <kbd>messages</kbd> 와 <kbd>templateCode</kbd> 는 필수 파라미터입니다.
* <kbd>commonApiUrl</kbd> 은 application.yml 에 명시된 URL 입니다.

## Failover 설정(알림톡 발송 실패시)

* 현재 X2BEE 카카오톡 채널은 Failover 설정이 <mark style="color:red;">True</mark>로 되어있어 <kbd>messages.useSmsFailover</kbd> <mark style="color:red;">변수 작성여부에 관계없이 true로 default 요청</mark>됩니다. \
  따라서 Failover 를 사용하지 않는다면 <kbd>messages.useSmsFailover</kbd> 변수를 false로 설정해야 합니다.
* <kbd>failoverConfig</kbd> 내 파라미터는 모두 Optional 로 작성하지 않으면 아래 각 파라미터 비고란에 적힌 내용과 같이 발송됩니다.
* [<kbd>messages.failoverConfig.from</kbd>](#user-content-fn-1)[^1] 의 경우 NCP Console 에 지정된 발신번호로 자동등록되오니 작성할 필요가 없습니다.

<table><thead><tr><th width="172.5555419921875">항목</th><th width="120.1112060546875">Mandatory</th><th width="88.2222900390625">Type</th><th>설명</th><th>비고</th></tr></thead><tbody><tr><td>plusFriendId</td><td>Mandatory</td><td>String</td><td>카카오톡 채널명 ((구)플러스친구 아이디)</td><td></td></tr><tr><td>templateCode</td><td>Mandatory</td><td>String</td><td>템플릿 코드</td><td></td></tr><tr><td>messages</td><td>Mandatory</td><td>Object</td><td>메시지 정보</td><td>- 아래 항목 참조 (messages.XXX)<br>- 최대 100개</td></tr><tr><td>messages.useSmsFailover</td><td>Optional</td><td>Boolean</td><td>SMS Failover 사용 여부</td><td>- Failover가 설정된 카카오톡 채널에서만 사용 가능<br>- 기본: 카카오톡 채널의 Failover 설정 여부를 따름</td></tr><tr><td>messages.failoverConfig</td><td>Optional</td><td>Object</td><td>Failover 설정</td><td>아래 항목 참조</td></tr><tr><td>messages.failoverConfig.type</td><td>Optional</td><td>String</td><td>Failover SMS 메시지 Type</td><td>- SMS 또는 LMS<br>- 기본: content 길이에 따라 자동 적용 (90 bytes 이하 SMS, 초과 LMS)</td></tr><tr><td>messages.failoverConfig.from</td><td>Optional</td><td>String</td><td>Failover SMS 발신번호</td><td>- 기본: Failover 설정 시 선택한 발신번호<br>- 승인되지 않은 발신번호 사용시 Failover 동작 안함</td></tr><tr><td>messages.failoverConfig.subject</td><td>Optional</td><td>String</td><td>Failover SMS 제목</td><td>- LMS type으로 동작할 때 사용<br>- 기본: 카카오톡 채널명</td></tr><tr><td>messages.failoverConfig.content</td><td>Optional</td><td>String</td><td>Failover SMS 내용</td><td>기본: 알림톡 메시지 내용 (버튼 제외)</td></tr></tbody></table>

***

[^1]:
