목차

반응형

1. 개요

비즈엠의 카카오톡 알림톡 확실히 엄청 좋은 기능이다. 별 다른 약관 동의 없이도 목적이 인정되면 카카오톡으로 보낼 수 있다는 것이 얼마나 좋은가?
근데 그건 알바아니고 개발자인 우리는 귀찮을 뿐
비즈엠 카카오톡 알림톡 전송 API를 개발하면서 정리할만한 부분을 정리해봤다.
다른 개발자들은 나보다는 빨리 원하는 결과에 도달하기를 바라며 오늘도 글을 싸 본다. 뿌직뿌직

특이사항이라면 보통 템플릿을 지원하면 request에 템플릿 id와 교체해줄 문구만 보내면 알아서 발송해주는 개념으로 생각했는데 그게 아니라 템플릿의 모든 정보(모든 문자, 기타 설정값)를 다 보내줘야 한다.
이 부분은 이해가 안 된다. 굳이...?
글고 뭔가 내가 특정 유저라는 것을 증명하는 API 키 같은 것도 없긴 하다. 근데 Send API 호출 난이도가 좀 높은 편이라서 필요 없는 것도 이해는 간다.

 

2. 필요한 정보

알림톡 전송 API를 호출하기 위해 필요한 최소한의 정보다.
전부 찾아오세요

 

비즈엠 로그인 ID

비즈엠 로그인할때 쓰는 로그인 ID

 

비즈엠 발신프로필키

발신 프로필 > 발신 프로필 목록 > 발신프로필키
전송하고자 하는 메시지의 발신프로필키 값과 메시지의 생성한 계정이 발신프로필이 동일해야 한다.

 

템플릿 ID

템플릿 > 템플릿 목록 > 보내고자 하는 메시지의 템플릿코드

 

메시지

저 메시지 내용을 1byte도 안 틀리고 똑같이 갖고 있어야 한다.

 

실제 받는 사람 전화번호

이건 그냥 본인 테스트용 전화번호로 해보자

 

버튼 정보

템플릿에 등록한 버튼 정보 전부 다 갖고 있어야 한다.

 

뭔 발송하는데 벌써부터 이렇게 복잡하냐...
일단 전부다 모아 왔으면 코드로 설명하기 전에 간단히 개념적으로 설명 들어가겠다.

 

비즈 엠 카카오톡 알림 톡 Send API의 호출하기 위한 정보는 아래와 같다.

let options = {
method:"POST",
"url":`https://alimtalk-api.bizmsg.kr/v2/sender/send`,
headers: {
"userid": "loginid",
"Content-Type": "application/json",
},
data: [{
        "message_type":"at","profile":"23456422626","phn":phone,
        "msg":tempMsg,
        "tmplId":join,
        "button1":

{
            "name": "마켓쿵 바로가기",
            "type": "WL",
            "url_mobile": "https://naver.com",
            "url_pc": "https://naver.com"
        }


    }]
}

비즈엠 로그인 ID는 헤더의 userid
이후 발송 요청에 대한 내용은 request body로 들어간다.(기본적으로 배열)

 

3. 코드

const templateInfo = {
    "join": {
        msgParamCount: 3,
        msgBody: "내용솰ㄹ라솰라내용솰ㄹ라솰라내용솰ㄹ라솰라내용솰ㄹ라솰라내용솰ㄹ라솰라내용솰ㄹ라솰라내용솰ㄹ라솰라내용솰ㄹ라솰라내용솰ㄹ라솰라내용솰ㄹ라솰라내용솰ㄹ라솰라",
        buttonInfo: {
            "name": "마켓쿵 바로가기",
            "type": "WL",
            "url_mobile": "https://naver.com",
            "url_pc": "https://naver.com"
        }
    },
    "payment":{msgParamCount:2, msgBody:"내용솰ㄹ라솰라내용솰ㄹ라솰라내용솰ㄹ라솰라내용솰ㄹ라솰라내용솰ㄹ라솰라내용솰ㄹ라솰라내용솰ㄹ라솰라내용솰ㄹ라솰라내용솰ㄹ라솰라내용솰ㄹ라솰라내용솰ㄹ라솰라",
        buttonInfo:{}
    },
    "login": {
        msgParamCount: 6,
        msgBody: "내용솰ㄹ라솰라내용솰ㄹ라솰라내용솰ㄹ라솰라내용솰ㄹ라솰라내용솰ㄹ라솰라내용솰ㄹ라솰라내용솰ㄹ라솰라내용솰ㄹ라솰라내용솰ㄹ라솰라내용솰ㄹ라솰라내용솰ㄹ라솰라",
        buttonInfo: {
            "name": "주문 내역 조회하기",
            "type": "WL",
            "url_mobile": "https://naver.com",
            "url_pc": "https://naver.com"
        }
    },
    "test": {
        msgParamCount: 5,
        msgBody: "내용솰ㄹ라솰라내용솰ㄹ라솰라내용솰ㄹ라솰라내용솰ㄹ라솰라내용솰ㄹ라솰라내용솰ㄹ라솰라내용솰ㄹ라솰라내용솰ㄹ라솰라내용솰ㄹ라솰라내용솰ㄹ라솰라내용솰ㄹ라솰라",
        buttonInfo: {
            "name": "배송 조회하기",
            "type": "WL",
            "url_mobile": "https://naver.com",
            "url_pc": "https://naver.com"
        }
    }
}

exports.alrimtalkService = {
    sendAlrimtalkMessage(templateId, messageParams, phone) {
        return new Promise(async (resolve, reject) => {
            //1. 정보 전부 제대로 들어왔는지 확인
            if(!templateId || !messageParams || !phone)
            {
                console.log("[alimtalk] : sendKakaoTalkMessage 함수 호출시 인자 설정이 제대로 되지 않았습니다.")
                return resolve("[alimtalk] : sendKakaoTalkMessage 함수 호출시 인자 설정이 제대로 되지 않았습니다.")
            }

            //2. 템플릿 정보 있는지 확인
            if(!(templateId in templateInfo))
            {
                console.log(`[alimtalk] : 존재하지 않는 템플릿 정보 ${templateId}`)
                return resolve(`[alimtalk] : 존재하지 않는 템플릿 정보 ${templateId}`)
            }

            //3. 템플릿 정보의 메시지 인자 수와 함수 호출된 메시지 인자 개수가 같은지 확인
            if(templateInfo[templateId].msgParamCount !== messageParams.length)
            {
                console.log(`[alimtalk] : 메시지 인자 개수가 일치하지 않습니다. ${templateInfo[templateId].msgParamCount} : ${messageParams.length}`)
                return resolve(`[alimtalk] : 메시지 인자 개수가 일치하지 않습니다. ${templateInfo[templateId].msgParamCount} : ${messageParams.length}`)
            }

            //전송 바디 생성
            let body = buildRequestBody(templateId, messageParams, phone)

            let options = {
                method:"POST",
                "url":`https://alimtalk-api.bizmsg.kr/v2/sender/send`,
                headers: {
                    "userid": "633463466",
                    "Content-Type": "application/json",
                },
                data: body
            }

            //4. 전송 제대로 됐는지 확인
            return await axios(options).then(result =>{
                if(result.data[0].code !== "fail") resolve(result)
                else
                {
                    console.log(`[alimtalk] : ${result.data[0].message}`)
                    resolve(result.data[0].message)
                }
            }).catch(error => {
                console.log(`[alimtalk] : ${result.data[0].message}`)
                resolve(`[alimtalk] : 비즈엠 전송 실패 ${error}`)
            })
        });
    }
}


function buildRequestBody(templateId, messageParams, phone)
{
    let tempMsg = templateInfo[templateId].msgBody
    for(let i = 0;i < templateInfo[templateId].msgParamCount;i++)
        tempMsg = tempMsg.replace(/#{.+}/,`${messageParams[i]}`)

    return [{
        "message_type":"at","profile":"757545775753","phn":phone,
        "msg":tempMsg,
        "tmplId":templateId,
        "button1":templateInfo[templateId].buttonInfo
    }]
}

//실제 사용 코드
await alrimtalk.alrimtalkService.sendAlrimtalkMessage("test", [purchase.order.sender.username, purchase.productName, purchase.order.orderNo, purchase.order.receiver.address1, purchase.delivery.number], purchase.order.sender.phone)

코드의 buildRequestBody와 templateInfo에 대한 부분은 꼭 필요한 건 아니지만 최소한 이 정도 설계 없이는 개판일 것 같아서 설계한 거니까 적당히 이해해주세여

반응형