카카오톡 공유하기 기능은 구현이 되었다고 가정하고, 카카오톡 공유하기 콜백 기능을 사용하는 법을 포스팅한다.

카카오톡 공유하기 기능을 사용하면 다른 사람에게 카카오톡 메시지를 보낼 수 있다. 이것은 프론트엔드에서 이루어지는 과정이라, 서버에서 공유하기가 실제로 이루어졌는지 알 방법이 없다.
우리 서비스에서는 칭찬 메시지를 공유할 때 SendPraise엔티티를 생성하고 고유한 uuid값을 가지게 한다. 그러나 버그나 이탈로 인해 전송이 이루어지지 않은 경우 SendPraise의 sendStatus값을 이용하여 관리하도록 하였다.
이것을 가능하게 하려면, 실제 공유가 되었는지 우리 서비스 서버에서 알 수 있어야 한다. 카카오톡 공유하기에서는 카카오톡 공유 완료 정보를 콜백을 통해 제공한다.(카카오 서버 -> 서비스 서버)
참고 : https://developers.kakao.com/docs/latest/ko/message/prerequisite#set-kakaotalk-sharing-callback

- [내 애플리케이션] > [메시지] > [카카오톡 공유 콜백] 메뉴에서 [콜백 등록] 버튼을 누릅니다.
- 카카오 서버로부터 알림을 받을 서비스 서버의 콜백(Callback) URL과 요청 방법(Method)을 설정합니다.
- 구현하려는 플랫폼별 카카오톡 공유 개발가이드를 참고하여 사용자 정의 파라미터를 설정합니다.
위 사진처럼, 카카오톡 공유하기가 완료되었을 때 우리 서비스 서버로 요청을 보낼 수 있도록, 콜백 URL을 등록 해 놓는다.
카카오 서버에서 해당 api주소로 GET/POST 요청을 보내는 것이기 때문에, aws 등에서 ip 화이트리스트에 추가해 주는 것을 고려해야 한다.
이용정책을 꼭 읽으라고 되어있는데 정상적으로 동작하지 않는다면 알아두면 좋을 것 같다.
200 OK로 응답을 보내야 하고, 카카오 서버의 IP를 알아두자.
참고 : https://developers.kakao.com/docs/latest/ko/message/callback#success
콜백 api는 GET 또는 POST 방식만 가능하다. 또한 카카오톡에서 콜백 api를 보낼 때 헤더와 파라미터로 많은 정보를 추가로 보내주는데, 이것을 받을 수 있도록 구현해야 한다.

.env로 가지고 있다가 넘겨주는 것이므로 아래의 프론트엔드쪽 코드를 참고하자.
RequestDto에 추가할 것이다.serverCallbackArgs를 이용하여 원하는 파라미터를 key-value형태로 보낼 수 있다.praiseUuid : uuid 형태로 보내는 것을 사용할 것이다.콜백받는 api를 GET으로 구현한다면
https://api.dodok-honeypot.com/api/send-praise/checkCHAT_TYPE=MemoChat&HASH_CHAT_ID=${HASH_CHAT_ID}&TEMPLATE_ID=10000&custom_parameter_key=custom_parameter_value"
위처럼 받게 될 것이고,
콜백받는 api를 POST로 구현한다면 RequestBody를 통해
{
"CHAT_TYPE":"MemoChat",
"HASH_CHAT_ID":"${HASH_CHAT_ID}",
"TEMPLATE_ID":10000,
"custom_parameter_key":"custom_parameter_value"
}
처럼 받게 될 것이다.
//SendPraiseController.java
/**
* 칭찬이 성공적으로 전송되었는지 확인할 수 있는 카카오 콜백 api
*/
@PostMapping("/check")
public ResponseEntity<SuccessResponse<?>> checkSendPraiseSent(
@RequestHeader("Authorization") String authrozitaion,
@RequestHeader("X-Kakao-Resource-ID") String kakaoResourceId,
@RequestHeader("User-Agent") String userAgent,
@RequestBody CheckSendPraiseSentReqDto req
) {
checkSendPraiseSentService.execute(req);
return SuccessResponse.ok(null);
}
//CheckSendPraiseSentReqDto.java
public record CheckSendPraiseSentReqDto(
String CHAT_TYPE, // 채팅방 유형 (MemoChat, DirectChat 등)
String HASH_CHAT_ID, // 채팅방 참고용 ID
String TEMPLATE_ID, // 사용된 메시지 템플릿 ID
String praiseUuid // 칭찬 메시지의 UUID
) {
}
콜백api를 통해 채팅방 유형을 전달받으면 해당 메세지의 SendStatus를 변경시켜주는 로직을 구현하였다.
// CheckSendPraiseSentService
@Slf4j
@Service
@Transactional
@RequiredArgsConstructor
public class CheckSendPraiseSentService {
public static final String MEMO_CHAT = "MemoChat"; // 나와의 채팅방
public static final String DIRECT_CHAT = "DirectChat"; // 다른 사용자와의 1:1 채팅방
public static final String MULTI_CHAT = "MultiChat"; // 다른 사용자들과의 그룹 채팅방
public static final String OPEN_DIRECT_CHAT = "OpenDirectChat"; // 1:1 오픈채팅방
public static final String OPEN_MULTI_CHAT = "OpenMultiChat"; // 그룹 오픈채팅방4
private final SendPraiseHelper sendPraiseHelper;
public void execute(CheckSendPraiseSentReqDto req) {
SendPraise sendPraise = sendPraiseHelper.findByUuidOrElseThrow(req.praiseUuid());
SendStatus newStatus = switch (req.CHAT_TYPE()) {
case MEMO_CHAT -> SendStatus.MYSELF;
case DIRECT_CHAT, OPEN_DIRECT_CHAT -> SendStatus.DIRECT;
case MULTI_CHAT, OPEN_MULTI_CHAT -> SendStatus.GROUP;
default -> SendStatus.FAIL;
};
sendPraise.updateSendStatus(newStatus);
log.info("[kakao-talk callback api] requestBody praiseUuid: " + req.praiseUuid());
log.info("[kakao-talk callback api] requestBody CHAT_TYPE: " + req.CHAT_TYPE());
log.info("[kakao-talk callback api] requestBody HASH_CHAT_ID: " + req.HASH_CHAT_ID());
}
}
프론트에서 카카오톡 공유하기 후, 1초에 한번씩 공유 완료 여부를 확인하는 폴링 api이다.
그냥 DB에 접근해서 SendStatus 값을 가져오는 api이다.
@GetMapping("/check")
public ResponseEntity<SuccessResponse<?>> getSendPraiseSent(
@RequestParam(name = "praise-uuid") String praiseUuid
) {
GetSendPraiseSentResDto res = getSendPraiseSentService.execute(praiseUuid);
return SuccessResponse.ok(res);
}
@Slf4j
@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class GetSendPraiseSentService {
private final SendPraiseHelper sendPraiseHelper;
private final SendPraiseMapper sendPraiseMapper;
public GetSendPraiseSentResDto execute(String praiseUuid) {
SendPraise sendPraise = sendPraiseHelper.findByUuidOrElseThrow(praiseUuid);
return sendPraiseMapper.toGetSendPraiseSentResDto(sendPraise);
}
}
카카오톡 공유하기 기능을 구현했다면, serverCallbackArgs만 추가해주면 된다.
사용자지정 파라미터가 필요없으면 넣지 않아도 된다.
//ComplimentSendContentPage.tsx
/* 2. 카카오 공유 */
if (isKakaoLoaded) {
const { Kakao, location } = window;
Kakao.Share.sendScrap({
requestUrl: location.origin + location.pathname,
templateId: 114602,
templateArgs: {
senderName: sender,
receiverName: receiverName,
content: content,
id: generatedUuid,
},
serverCallbackArgs: { praiseUuid: generatedUuid },
);
}
}
이 기능을 활용한다면, 토스나 카뱅에서 진행하는 공유하기를 통해 뽑기 기회 얻기 기능을 만들 수 있을 것 같다.