Skip to content

Commit

Permalink
YEL-170 [feat] apple notification slack webhook
Browse files Browse the repository at this point in the history
YEL-170 [feat] apple notification slack webhook
  • Loading branch information
hyeonjeongs authored Sep 26, 2023
2 parents 2ab2e9c + 8e111f4 commit 5cc7dd2
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import com.yello.server.domain.purchase.dto.request.AppleNotificationRequest;
import com.yello.server.domain.purchase.service.PurchaseService;
import com.yello.server.global.common.dto.BaseResponse;
import com.yello.server.infrastructure.slack.annotation.SlackPurchaseNotification;
import com.yello.server.infrastructure.slack.annotation.SlackApplePurchaseNotification;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
Expand All @@ -18,7 +18,7 @@ public class PurchaseNotificationController {
private final PurchaseService purchaseService;

@PostMapping("/v2/apple/notifications")
@SlackPurchaseNotification
@SlackApplePurchaseNotification
public BaseResponse appleNotification(
@RequestBody AppleNotificationRequest request
) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.yello.server.infrastructure.slack.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SlackApplePurchaseNotification {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.yello.server.infrastructure.slack.aspect;

import com.yello.server.infrastructure.slack.factory.SlackWebhookMessageFactory;
import javax.servlet.http.HttpServletRequest;
import net.gpedro.integrations.slack.SlackApi;
import net.gpedro.integrations.slack.SlackMessage;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

@Aspect
@Component
public class SlackApplePurchaseNotificationAspect {

private final SlackApi slackApplePurchaseApi;
private final SlackWebhookMessageFactory slackWebhookMessageFactory;
private final TaskExecutor taskExecutor;

public SlackApplePurchaseNotificationAspect(
@Qualifier("slackApplePurchaseNotificationApi") SlackApi slackApplePurchaseApi,
SlackWebhookMessageFactory slackWebhookMessageFactory,
TaskExecutor taskExecutor) {
this.slackApplePurchaseApi = slackApplePurchaseApi;
this.slackWebhookMessageFactory = slackWebhookMessageFactory;
this.taskExecutor = taskExecutor;
}

@Around("@annotation(com.yello.server.infrastructure.slack.annotation.SlackApplePurchaseNotification)")
Object applePurchaseNotification(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
HttpServletRequest request =
((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
.getRequest();

SlackMessage slackMessage = slackWebhookMessageFactory.generateAppleSlackPurchaseMessage(
request
);

Runnable runnable = () -> slackApplePurchaseApi.call(slackMessage);
taskExecutor.execute(runnable);

return proceedingJoinPoint.proceed();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ public class SlackConfiguration {
@Value("${slack.token.sign-up}")
String slackTokenForSignUp;

@Value("${slack.token.apple-bank-alarm}")
String slackTokenForApplePurchaseNotification;

@Bean
SlackApi slackErrorApi() {
return new SlackApi("https://hooks.slack.com/services/" + slackTokenForError);
Expand All @@ -31,4 +34,10 @@ SlackApi slackPurchaseApi() {
SlackApi slackSignUpApi() {
return new SlackApi("https://hooks.slack.com/services/" + slackTokenForSignUp);
}

@Bean
SlackApi slackApplePurchaseNotificationApi() {
return new SlackApi(
"https://hooks.slack.com/services/" + slackTokenForApplePurchaseNotification);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package com.yello.server.infrastructure.slack.factory;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yello.server.domain.authorization.service.TokenProvider;
import com.yello.server.domain.purchase.dto.apple.AppleNotificationPayloadVO;
import com.yello.server.domain.purchase.service.PurchaseManager;
import com.yello.server.domain.user.entity.User;
import com.yello.server.domain.user.repository.UserRepository;
import com.yello.server.global.common.factory.TimeFactory;
Expand Down Expand Up @@ -33,8 +37,12 @@ public class SlackWebhookMessageFactory {
private static final String SIGNUP_TITLE = "신규 유저가 가입하였습니다. ";
private static final String SIGNUP_USERNAME = "옐로 온보딩";

private static final String APPLE_PURCHASE_ALARM_TITLE = "애플이 결제 관련 알림을 보냈습니다.";
private static final String APPLE_PURCHASE_ALARM_USERNAME = "애플 뱅크 알림";

private final UserRepository userRepository;
private final TokenProvider tokenProvider;
private final PurchaseManager purchaseManager;

private static String getRequestBody(HttpServletRequest request) throws IOException {

Expand All @@ -44,7 +52,7 @@ private static String getRequestBody(HttpServletRequest request) throws IOExcept

try {
InputStream inputStream = request.getInputStream();
if (inputStream != null) {
if (inputStream!=null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
char[] charBuffer = new char[128];
int bytesRead = -1;
Expand All @@ -55,7 +63,7 @@ private static String getRequestBody(HttpServletRequest request) throws IOExcept
} catch (IOException ex) {
throw ex;
} finally {
if (bufferedReader != null) {
if (bufferedReader!=null) {
try {
bufferedReader.close();
} catch (IOException ex) {
Expand Down Expand Up @@ -96,6 +104,15 @@ public SlackMessage generateSlackSignUpMessage(
.setUsername(SIGNUP_USERNAME);
}

public SlackMessage generateAppleSlackPurchaseMessage(
HttpServletRequest request
) throws IOException {
return new SlackMessage()
.setAttachments(generateSlackApplePurchaseAttachment(request))
.setText(APPLE_PURCHASE_ALARM_TITLE)
.setUsername(APPLE_PURCHASE_ALARM_USERNAME);
}

private List<SlackAttachment> generateSlackErrorAttachment(
HttpServletRequest request,
Exception exception
Expand Down Expand Up @@ -139,13 +156,27 @@ private List<SlackAttachment> generateSlackSignUpAttachment(
return Collections.singletonList(slackAttachment);
}

private List<SlackAttachment> generateSlackApplePurchaseAttachment(
HttpServletRequest request
) throws IOException {
final SlackAttachment slackAttachment = new SlackAttachment()
.setFallback("good")
.setColor("good")
.setTitle(APPLE_PURCHASE_ALARM_TITLE)
.setTitleLink(request.getContextPath())
.setText(APPLE_PURCHASE_ALARM_TITLE)
.setFields(generateSlackAppleFieldList(request));
return Collections.singletonList(slackAttachment);
}

private List<SlackField> generateSlackFieldList(
HttpServletRequest request
) throws IOException {
final String authHeader = request.getHeader(HttpHeaders.AUTHORIZATION);
final String token = authHeader == null ? "null" : authHeader.substring("Bearer ".length());
final Long userId = authHeader == null ? -1L : tokenProvider.getUserId(token);
final Optional<User> user = authHeader == null ? Optional.empty() : userRepository.findById(userId);
final String token = authHeader==null ? "null" : authHeader.substring("Bearer ".length());
final Long userId = authHeader==null ? -1L : tokenProvider.getUserId(token);
final Optional<User> user =
authHeader==null ? Optional.empty() : userRepository.findById(userId);
final String yelloId = user.isPresent() ? user.get().getYelloId() : "null";
final String deviceToken = user.isPresent() ? user.get().getDeviceToken() : "null";

Expand Down Expand Up @@ -177,4 +208,41 @@ private List<SlackField> generateSlackSimpleFieldList(
.setValue(getRequestBody(request))
);
}

private List<SlackField> generateSlackAppleFieldList(
HttpServletRequest request
) throws IOException {
return Arrays.asList(
new SlackField().setTitle("Request Method").setValue(request.getMethod()),
new SlackField().setTitle("Request URL").setValue(request.getRequestURL().toString()),
new SlackField().setTitle("Request Time")
.setValue(TimeFactory.toDateFormattedString(LocalDateTime.now())),
new SlackField().setTitle("Request IP").setValue(request.getRemoteAddr()),
new SlackField().setTitle("Request Headers")
.setValue(request.toString()),
new SlackField().setTitle("Request Body")
.setValue(generateSlackAppleNotificationRequestField(request))
);
}

private String generateSlackAppleNotificationRequestField(
HttpServletRequest request
) throws IOException {
String jsonString = getRequestBody(request);
ObjectMapper objectMapper = new ObjectMapper();
String[] payload = new String[1];
try {
JsonNode jsonNode = objectMapper.readTree(jsonString);
if (jsonNode.isObject()) {
jsonNode.fields().forEachRemaining(entry -> {
payload[0] = entry.getValue().asText();
});
}
} catch (Exception e) {
e.printStackTrace();
}
AppleNotificationPayloadVO payloadVO = purchaseManager.decodeApplePayload(payload[0]);

return payloadVO.toString();
}
}

0 comments on commit 5cc7dd2

Please sign in to comment.