From 1ff52adbf76f352695dd458d4d7a04665806bded Mon Sep 17 00:00:00 2001 From: hyeonjeongs Date: Sun, 10 Sep 2023 16:37:47 +0900 Subject: [PATCH 1/2] =?UTF-8?q?YEL-154=20[feat]=20apple=20notification=20-?= =?UTF-8?q?=20=EA=B5=AC=EB=8F=85=20=EC=B7=A8=EC=86=8C=ED=95=9C=20=EA=B2=BD?= =?UTF-8?q?=EC=9A=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../filter/JwtExceptionFilter.java | 7 +-- .../authorization/filter/JwtFilter.java | 3 +- .../PurchaseNotificationController.java | 26 +++++++++++ .../dto/apple/AppleNotificationPayloadVO.java | 14 ++++++ .../dto/apple/ApplePayloadDataVO.java | 13 ++++++ .../dto/apple/ApplePayloadSummaryVO.java | 11 +++++ .../dto/request/AppleNotificationRequest.java | 7 +++ .../response/AppleNotificationResponse.java | 10 +++++ .../purchase/service/PurchaseManager.java | 8 ++++ .../purchase/service/PurchaseManagerImpl.java | 45 +++++++++++++++++++ .../purchase/service/PurchaseService.java | 42 ++++++++++++++--- .../yello/server/global/common/ErrorCode.java | 1 + .../server/global/common/SuccessCode.java | 1 + .../common/factory/DecodeTokenFactory.java | 8 +++- .../common/factory/TokenFactoryImpl.java | 1 - .../global/common/util/ConstantUtil.java | 8 ++++ .../domain/purchase/FakePurchaseManager.java | 17 +++++++ 17 files changed, 211 insertions(+), 11 deletions(-) create mode 100644 src/main/java/com/yello/server/domain/purchase/controller/PurchaseNotificationController.java create mode 100644 src/main/java/com/yello/server/domain/purchase/dto/apple/AppleNotificationPayloadVO.java create mode 100644 src/main/java/com/yello/server/domain/purchase/dto/apple/ApplePayloadDataVO.java create mode 100644 src/main/java/com/yello/server/domain/purchase/dto/apple/ApplePayloadSummaryVO.java create mode 100644 src/main/java/com/yello/server/domain/purchase/dto/request/AppleNotificationRequest.java create mode 100644 src/main/java/com/yello/server/domain/purchase/dto/response/AppleNotificationResponse.java diff --git a/src/main/java/com/yello/server/domain/authorization/filter/JwtExceptionFilter.java b/src/main/java/com/yello/server/domain/authorization/filter/JwtExceptionFilter.java index 5d24fc9f..9b7a6bcd 100644 --- a/src/main/java/com/yello/server/domain/authorization/filter/JwtExceptionFilter.java +++ b/src/main/java/com/yello/server/domain/authorization/filter/JwtExceptionFilter.java @@ -46,6 +46,7 @@ protected void doFilterInternal( || requestPath.startsWith("/docs") || requestPath.startsWith("/actuator") || requestPath.startsWith("/prometheus") || requestPath.startsWith("/api/v1/admin/login") + || requestPath.startsWith("/v2/apple/notifications") || (requestPath.startsWith("/api/v1/auth") && !requestPath.startsWith("/api/v1/auth/token/issue"))) { filterChain.doFilter(request, response); @@ -59,8 +60,8 @@ protected void doFilterInternal( log.info("Authorization-access : {}", accessHeader); log.info("Authorization-refresh : {}", refreshHeader); - if (accessHeader == null || !accessHeader.startsWith(BEARER) - || refreshHeader == null || !refreshHeader.startsWith(BEARER)) { + if (accessHeader==null || !accessHeader.startsWith(BEARER) + || refreshHeader==null || !refreshHeader.startsWith(BEARER)) { throw new CustomAuthenticationException(AUTHENTICATION_ERROR); } @@ -71,7 +72,7 @@ protected void doFilterInternal( val accessHeader = request.getHeader(AUTHORIZATION); log.info("Authorization : {}", accessHeader); - if (accessHeader == null || !accessHeader.startsWith(BEARER)) { + if (accessHeader==null || !accessHeader.startsWith(BEARER)) { throw new CustomAuthenticationException(AUTHENTICATION_ERROR); } diff --git a/src/main/java/com/yello/server/domain/authorization/filter/JwtFilter.java b/src/main/java/com/yello/server/domain/authorization/filter/JwtFilter.java index 1c15b2a5..260fb24e 100644 --- a/src/main/java/com/yello/server/domain/authorization/filter/JwtFilter.java +++ b/src/main/java/com/yello/server/domain/authorization/filter/JwtFilter.java @@ -39,7 +39,8 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse || requestPath.startsWith("/docs") || requestPath.startsWith("/actuator") || requestPath.startsWith("/prometheus") || requestPath.startsWith("/api/v1/admin/login") - || requestPath.startsWith("/api/v1/auth")) { + || requestPath.startsWith("/api/v1/auth") + || requestPath.startsWith("/v2/apple/notifications")) { filterChain.doFilter(request, response); return; } diff --git a/src/main/java/com/yello/server/domain/purchase/controller/PurchaseNotificationController.java b/src/main/java/com/yello/server/domain/purchase/controller/PurchaseNotificationController.java new file mode 100644 index 00000000..a10713fa --- /dev/null +++ b/src/main/java/com/yello/server/domain/purchase/controller/PurchaseNotificationController.java @@ -0,0 +1,26 @@ +package com.yello.server.domain.purchase.controller; + +import static com.yello.server.global.common.SuccessCode.POST_APPLE_NOTIFICATION_SUCCESS; + +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 lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +public class PurchaseNotificationController { + + private final PurchaseService purchaseService; + + @PostMapping("/v2/apple/notifications") + public BaseResponse appleNotification( + @RequestBody AppleNotificationRequest request + ) { + purchaseService.appleNotification(request); + return BaseResponse.success(POST_APPLE_NOTIFICATION_SUCCESS); + } +} diff --git a/src/main/java/com/yello/server/domain/purchase/dto/apple/AppleNotificationPayloadVO.java b/src/main/java/com/yello/server/domain/purchase/dto/apple/AppleNotificationPayloadVO.java new file mode 100644 index 00000000..a1238024 --- /dev/null +++ b/src/main/java/com/yello/server/domain/purchase/dto/apple/AppleNotificationPayloadVO.java @@ -0,0 +1,14 @@ +package com.yello.server.domain.purchase.dto.apple; + +import lombok.Builder; + +@Builder +public record AppleNotificationPayloadVO( + String notificationType, + String subType, + ApplePayloadDataVO data, + String notificationUUID + +) { + +} diff --git a/src/main/java/com/yello/server/domain/purchase/dto/apple/ApplePayloadDataVO.java b/src/main/java/com/yello/server/domain/purchase/dto/apple/ApplePayloadDataVO.java new file mode 100644 index 00000000..56236b79 --- /dev/null +++ b/src/main/java/com/yello/server/domain/purchase/dto/apple/ApplePayloadDataVO.java @@ -0,0 +1,13 @@ +package com.yello.server.domain.purchase.dto.apple; + +public record ApplePayloadDataVO( + String appAppleId, + String bundleId, + String environment, + String signedTransactionInfo, + String signedRenewalInfo, + int status + +) { + +} diff --git a/src/main/java/com/yello/server/domain/purchase/dto/apple/ApplePayloadSummaryVO.java b/src/main/java/com/yello/server/domain/purchase/dto/apple/ApplePayloadSummaryVO.java new file mode 100644 index 00000000..bcd2fa1e --- /dev/null +++ b/src/main/java/com/yello/server/domain/purchase/dto/apple/ApplePayloadSummaryVO.java @@ -0,0 +1,11 @@ +package com.yello.server.domain.purchase.dto.apple; + +public record ApplePayloadSummaryVO( + String requestIdentifier, + String environment, + String appAppleId, + String bundleId, + String productId +) { + +} diff --git a/src/main/java/com/yello/server/domain/purchase/dto/request/AppleNotificationRequest.java b/src/main/java/com/yello/server/domain/purchase/dto/request/AppleNotificationRequest.java new file mode 100644 index 00000000..dcf26402 --- /dev/null +++ b/src/main/java/com/yello/server/domain/purchase/dto/request/AppleNotificationRequest.java @@ -0,0 +1,7 @@ +package com.yello.server.domain.purchase.dto.request; + +public record AppleNotificationRequest( + String signedPayload +) { + +} diff --git a/src/main/java/com/yello/server/domain/purchase/dto/response/AppleNotificationResponse.java b/src/main/java/com/yello/server/domain/purchase/dto/response/AppleNotificationResponse.java new file mode 100644 index 00000000..dd40aa6a --- /dev/null +++ b/src/main/java/com/yello/server/domain/purchase/dto/response/AppleNotificationResponse.java @@ -0,0 +1,10 @@ +package com.yello.server.domain.purchase.dto.response; + +import lombok.Builder; + +@Builder +public record AppleNotificationResponse( + +) { + +} diff --git a/src/main/java/com/yello/server/domain/purchase/service/PurchaseManager.java b/src/main/java/com/yello/server/domain/purchase/service/PurchaseManager.java index 293a0def..5748f89f 100644 --- a/src/main/java/com/yello/server/domain/purchase/service/PurchaseManager.java +++ b/src/main/java/com/yello/server/domain/purchase/service/PurchaseManager.java @@ -1,5 +1,6 @@ package com.yello.server.domain.purchase.service; +import com.yello.server.domain.purchase.dto.apple.AppleNotificationPayloadVO; import com.yello.server.domain.purchase.dto.apple.TransactionInfoResponse; import com.yello.server.domain.purchase.entity.Gateway; import com.yello.server.domain.purchase.entity.ProductType; @@ -17,4 +18,11 @@ Purchase createTicket(User user, ProductType productType, Gateway gateway, void handleAppleTransactionError(ResponseEntity response, String transactionId); + AppleNotificationPayloadVO decodeApplePayload(String signedPayload); + + String decodeAppleNotificationData(String signedTransactionInfo); + + void changeSubscriptionStatus(User user, String transactionId, + AppleNotificationPayloadVO payloadVO); + } diff --git a/src/main/java/com/yello/server/domain/purchase/service/PurchaseManagerImpl.java b/src/main/java/com/yello/server/domain/purchase/service/PurchaseManagerImpl.java index babadc6e..b691f793 100644 --- a/src/main/java/com/yello/server/domain/purchase/service/PurchaseManagerImpl.java +++ b/src/main/java/com/yello/server/domain/purchase/service/PurchaseManagerImpl.java @@ -2,7 +2,11 @@ import static com.yello.server.global.common.ErrorCode.APPLE_TOKEN_SERVER_EXCEPTION; import static com.yello.server.global.common.ErrorCode.GOOGLE_SUBSCRIPTIONS_SUBSCRIPTION_EXCEPTION; +import static com.yello.server.global.common.ErrorCode.NOT_FOUND_TRANSACTION_EXCEPTION; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.yello.server.domain.purchase.dto.apple.AppleNotificationPayloadVO; import com.yello.server.domain.purchase.dto.apple.TransactionInfoResponse; import com.yello.server.domain.purchase.entity.Gateway; import com.yello.server.domain.purchase.entity.ProductType; @@ -12,7 +16,11 @@ import com.yello.server.domain.purchase.repository.PurchaseRepository; import com.yello.server.domain.user.entity.Subscribe; import com.yello.server.domain.user.entity.User; +import com.yello.server.domain.user.repository.UserRepository; +import com.yello.server.global.common.factory.DecodeTokenFactory; import com.yello.server.global.common.factory.TokenFactory; +import com.yello.server.global.common.util.ConstantUtil; +import java.util.Map; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; @@ -23,6 +31,7 @@ public class PurchaseManagerImpl implements PurchaseManager { private final PurchaseRepository purchaseRepository; private final TokenFactory tokenFactory; + private final UserRepository userRepository; @Override public Purchase createSubscribe(User user, Gateway gateway, String transactionId) { @@ -56,5 +65,41 @@ public void handleAppleTransactionError(ResponseEntity }); } + @Override + public AppleNotificationPayloadVO decodeApplePayload(String signedPayload) { + String jsonPayload = DecodeTokenFactory.decodePayload(signedPayload); + + ObjectMapper objectMapper = new ObjectMapper(); + try { + AppleNotificationPayloadVO payloadVO = + objectMapper.readValue(jsonPayload, AppleNotificationPayloadVO.class); + System.out.println(payloadVO + " 입니다아아아아아"); + return payloadVO; + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + @Override + public String decodeAppleNotificationData(String signedTransactionInfo) { + + Map decodeToken = DecodeTokenFactory.decodeToken(signedTransactionInfo); + String decodeTransactionId = decodeToken.get("transactionId").toString(); + + Purchase purchase = purchaseRepository.findByTransactionId(decodeTransactionId) + .orElseThrow(() -> new PurchaseConflictException(NOT_FOUND_TRANSACTION_EXCEPTION)); + + return purchase.getTransactionId(); + } + + @Override + public void changeSubscriptionStatus(User user, String transactionId, + AppleNotificationPayloadVO payloadVO) { + if (payloadVO.subType().equals(ConstantUtil.APPLE_SUBTYPE_AUTO_RENEW_DISABLED) + && !user.getSubscribe().equals(Subscribe.NORMAL)) { + user.setSubscribe(Subscribe.NORMAL); + } + } + } diff --git a/src/main/java/com/yello/server/domain/purchase/service/PurchaseService.java b/src/main/java/com/yello/server/domain/purchase/service/PurchaseService.java index 96c79c64..a1820cee 100644 --- a/src/main/java/com/yello/server/domain/purchase/service/PurchaseService.java +++ b/src/main/java/com/yello/server/domain/purchase/service/PurchaseService.java @@ -9,8 +9,12 @@ import static com.yello.server.global.common.ErrorCode.GOOGLE_TOKEN_FIELD_NOT_FOUND_EXCEPTION; import static com.yello.server.global.common.ErrorCode.GOOGLE_TOKEN_FORBIDDEN_EXCEPTION; import static com.yello.server.global.common.ErrorCode.GOOGLE_TOKEN_SERVER_EXCEPTION; +import static com.yello.server.global.common.ErrorCode.NOT_FOUND_NOTIFICATION_TYPE_EXCEPTION; import static com.yello.server.global.common.ErrorCode.NOT_FOUND_TRANSACTION_EXCEPTION; import static com.yello.server.global.common.ErrorCode.SUBSCRIBE_ACTIVE_EXCEPTION; +import static com.yello.server.global.common.util.ConstantUtil.APPLE_NOTIFICATION_CONSUMPTION_REQUEST; +import static com.yello.server.global.common.util.ConstantUtil.APPLE_NOTIFICATION_REFUND; +import static com.yello.server.global.common.util.ConstantUtil.APPLE_NOTIFICATION_SUBSCRIPTION_STATUS_CHANGE; import static com.yello.server.global.common.util.ConstantUtil.FIVE_TICKET_ID; import static com.yello.server.global.common.util.ConstantUtil.GOOGLE_FIVE_TICKET_ID; import static com.yello.server.global.common.util.ConstantUtil.GOOGLE_TWO_TICKET_ID; @@ -20,9 +24,11 @@ import com.google.gson.Gson; import com.google.gson.JsonObject; +import com.yello.server.domain.purchase.dto.apple.AppleNotificationPayloadVO; import com.yello.server.domain.purchase.dto.apple.AppleTransaction; import com.yello.server.domain.purchase.dto.apple.TransactionInfoResponse; import com.yello.server.domain.purchase.dto.request.AppleInAppRefundRequest; +import com.yello.server.domain.purchase.dto.request.AppleNotificationRequest; import com.yello.server.domain.purchase.dto.request.GoogleSubscriptionGetRequest; import com.yello.server.domain.purchase.dto.request.GoogleTicketGetRequest; import com.yello.server.domain.purchase.dto.response.GoogleSubscriptionGetResponse; @@ -77,7 +83,7 @@ public UserSubscribeNeededResponse getUserSubscribe(User user, LocalDateTime tim final Optional mostRecentPurchase = purchaseRepository.findTopByUserAndProductTypeOrderByCreatedAtDesc( user, ProductType.YELLO_PLUS); - final Boolean isSubscribeNeeded = user.getSubscribe() == Subscribe.CANCELED + final Boolean isSubscribeNeeded = user.getSubscribe()==Subscribe.CANCELED && mostRecentPurchase.isPresent() && Duration.between(mostRecentPurchase.get().getCreatedAt(), time).getSeconds() < 1 * 24 * 60 * 60; @@ -94,7 +100,7 @@ public void verifyAppleSubscriptionTransaction(Long userId, purchaseManager.handleAppleTransactionError(verifyReceiptResponse, request.transactionId()); - if (user.getSubscribe() == Subscribe.ACTIVE) { + if (user.getSubscribe()==Subscribe.ACTIVE) { throw new SubscriptionConflictException(SUBSCRIBE_ACTIVE_EXCEPTION); } @@ -110,6 +116,7 @@ public void verifyAppleSubscriptionTransaction(Long userId, public void verifyAppleTicketTransaction(Long userId, AppleTransaction request) { final ResponseEntity verifyReceiptResponse = apiWebClient.appleGetTransaction(request); + final User user = userRepository.getById(userId); purchaseManager.handleAppleTransactionError(verifyReceiptResponse, request.transactionId()); @@ -141,7 +148,7 @@ public GoogleSubscriptionGetResponse verifyGoogleSubscriptionTransaction(Long us User user = userRepository.getById(userId); // exception - if (user.getSubscribe() != Subscribe.NORMAL) { + if (user.getSubscribe()!=Subscribe.NORMAL) { throw new PurchaseConflictException(GOOGLE_SUBSCRIPTIONS_FORBIDDEN_EXCEPTION); } @@ -187,7 +194,7 @@ public GoogleSubscriptionGetResponse verifyGoogleSubscriptionTransaction(Long us GOOGLE_SUBSCRIPTION_TRANSACTION_EXPIRED_EXCEPTION); } case ConstantUtil.GOOGLE_PURCHASE_SUBSCRIPTION_CANCELED -> { - if (user.getSubscribe() == Subscribe.CANCELED) { + if (user.getSubscribe()==Subscribe.CANCELED) { throw new GoogleBadRequestException( GOOGLE_SUBSCRIPTION_DUPLICATED_CANCEL_EXCEPTION); } else { @@ -241,7 +248,7 @@ public GoogleTicketGetResponse verifyGoogleTicketTransaction(Long userId, throw new GoogleTokenServerErrorException(GOOGLE_TOKEN_SERVER_EXCEPTION); } - if (inAppResponse.getBody().purchaseState() == 0) { + if (inAppResponse.getBody().purchaseState()==0) { purchaseRepository.findByTransactionId(inAppResponse.getBody().orderId()) .ifPresent(action -> { throw new PurchaseConflictException( @@ -283,6 +290,31 @@ public void refundInAppApple(Long userId, AppleInAppRefundRequest request) { user.setSubscribe(Subscribe.NORMAL); } + @Transactional + public void appleNotification(AppleNotificationRequest request) { + + AppleNotificationPayloadVO payloadVO = + purchaseManager.decodeApplePayload(request.signedPayload()); + String transactionId = + purchaseManager.decodeAppleNotificationData(payloadVO.data().signedTransactionInfo()); + Purchase purchase = purchaseRepository.findByTransactionId(transactionId) + .orElseThrow(() -> new PurchaseNotFoundException(NOT_FOUND_TRANSACTION_EXCEPTION)); + + switch (payloadVO.notificationType()) { + case APPLE_NOTIFICATION_CONSUMPTION_REQUEST: + break; + case APPLE_NOTIFICATION_SUBSCRIPTION_STATUS_CHANGE: + purchaseManager.changeSubscriptionStatus(purchase.getUser(), transactionId, + payloadVO); + break; + case APPLE_NOTIFICATION_REFUND: + System.out.println("dd"); + break; + default: + throw new PurchaseNotFoundException(NOT_FOUND_NOTIFICATION_TYPE_EXCEPTION); + } + } + public ProductType getProductType(String googleInAppId) { if (googleInAppId.equals(ConstantUtil.GOOGLE_ONE_TICKET_ID)) { return ProductType.ONE_TICKET; diff --git a/src/main/java/com/yello/server/global/common/ErrorCode.java b/src/main/java/com/yello/server/global/common/ErrorCode.java index 4db6383d..2fc3cee2 100644 --- a/src/main/java/com/yello/server/global/common/ErrorCode.java +++ b/src/main/java/com/yello/server/global/common/ErrorCode.java @@ -83,6 +83,7 @@ public enum ErrorCode { "Google OAuth 2.0 특정 토큰이 DB에 없습니다. DBA에게 문의해주세요."), USER_ADMIN_NOT_FOUND_EXCEPTION(NOT_FOUND, "해당 Admin이 존재하지 않습니다."), NOT_EQUAL_TRANSACTION_EXCEPTION(NOT_FOUND, "동일하지 않은 거래입니다."), + NOT_FOUND_NOTIFICATION_TYPE_EXCEPTION(NOT_FOUND, "존재하지 않는 알림 타입 입니다"), /** * 409 CONFLICT diff --git a/src/main/java/com/yello/server/global/common/SuccessCode.java b/src/main/java/com/yello/server/global/common/SuccessCode.java index 5badcb00..f61a418e 100644 --- a/src/main/java/com/yello/server/global/common/SuccessCode.java +++ b/src/main/java/com/yello/server/global/common/SuccessCode.java @@ -39,6 +39,7 @@ public enum SuccessCode { READ_COOLDOWN_ADMIN_SUCCESS(OK, "어드민 페이지 쿨다운 조회에 성공하였습니다."), DELETE_USER_ADMIN_SUCCESS(OK, "어드민 권환으로 유저 삭제에 성공하였습니다."), DELETE_COOLDOWN_ADMIN_SUCCESS(OK, "어드민 권환으로 쿨다운 삭제에 성공하였습니다."), + POST_APPLE_NOTIFICATION_SUCCESS(OK, "apple 알림 처리에 성공하였습니다."), /** * 201 CREATED diff --git a/src/main/java/com/yello/server/global/common/factory/DecodeTokenFactory.java b/src/main/java/com/yello/server/global/common/factory/DecodeTokenFactory.java index 993042aa..e01ba8c9 100644 --- a/src/main/java/com/yello/server/global/common/factory/DecodeTokenFactory.java +++ b/src/main/java/com/yello/server/global/common/factory/DecodeTokenFactory.java @@ -11,8 +11,14 @@ public static Map decodeToken(String jwtToken) { final String payload = new String(java.util.Base64.getUrlDecoder().decode(payloadJWT)); BasicJsonParser jsonParser = new BasicJsonParser(); Map jsonArray = jsonParser.parseMap(payload); - + return jsonArray; } + public static String decodePayload(String payload) { + final String decodePayload = new String(java.util.Base64.getUrlDecoder().decode(payload)); + + return decodePayload; + } + } diff --git a/src/main/java/com/yello/server/global/common/factory/TokenFactoryImpl.java b/src/main/java/com/yello/server/global/common/factory/TokenFactoryImpl.java index 7674752a..b5b6d7ba 100644 --- a/src/main/java/com/yello/server/global/common/factory/TokenFactoryImpl.java +++ b/src/main/java/com/yello/server/global/common/factory/TokenFactoryImpl.java @@ -35,7 +35,6 @@ public class TokenFactoryImpl implements TokenFactory { @Override public String generateAppleToken() { setKey(); - return Jwts.builder() .setHeaderParam("kid", kid) .setIssuer(iss) diff --git a/src/main/java/com/yello/server/global/common/util/ConstantUtil.java b/src/main/java/com/yello/server/global/common/util/ConstantUtil.java index 360ffd36..0940bdb7 100644 --- a/src/main/java/com/yello/server/global/common/util/ConstantUtil.java +++ b/src/main/java/com/yello/server/global/common/util/ConstantUtil.java @@ -46,6 +46,14 @@ public class ConstantUtil { public static final String GOOGLE_PURCHASE_INAPP_CANCELED = "CANCELED"; public static final String YELLO_FEMALE = "yello_female"; public static final String YELLO_MALE = "yello_male"; + public static final String APPLE_NOTIFICATION_CONSUMPTION_REQUEST = "CONSUMPTION_REQUEST"; + public static final String APPLE_NOTIFICATION_SUBSCRIPTION_STATUS_CHANGE = + "DID_CHANGE_RENEWAL_STATUS"; + public static final String APPLE_NOTIFICATION_REFUND = "REFUND"; + public static final String APPLE_NOTIFICATION_EXPIRED = "EXPIRED"; + public static final String APPLE_NOTIFICATION_TEST = "TEST"; + public static final String APPLE_SUBTYPE_AUTO_RENEW_DISABLED = "AUTO_RENEW_DISABLED"; + public static final String APPLE_SUBTYPE_VOLUNTARY = "VOLUNTARY"; private ConstantUtil() { diff --git a/src/test/java/com/yello/server/domain/purchase/FakePurchaseManager.java b/src/test/java/com/yello/server/domain/purchase/FakePurchaseManager.java index 4d782e26..6a76966f 100644 --- a/src/test/java/com/yello/server/domain/purchase/FakePurchaseManager.java +++ b/src/test/java/com/yello/server/domain/purchase/FakePurchaseManager.java @@ -3,6 +3,7 @@ import static com.yello.server.global.common.ErrorCode.APPLE_TOKEN_SERVER_EXCEPTION; import static com.yello.server.global.common.ErrorCode.GOOGLE_SUBSCRIPTIONS_SUBSCRIPTION_EXCEPTION; +import com.yello.server.domain.purchase.dto.apple.AppleNotificationPayloadVO; import com.yello.server.domain.purchase.dto.apple.TransactionInfoResponse; import com.yello.server.domain.purchase.entity.Gateway; import com.yello.server.domain.purchase.entity.ProductType; @@ -51,4 +52,20 @@ public void handleAppleTransactionError(ResponseEntity throw new PurchaseConflictException(GOOGLE_SUBSCRIPTIONS_SUBSCRIPTION_EXCEPTION); }); } + + @Override + public AppleNotificationPayloadVO decodeApplePayload(String signedPayload) { + return null; + } + + @Override + public String decodeAppleNotificationData(String signedTransactionInfo) { + return null; + } + + @Override + public void changeSubscriptionStatus(User user, String transactionId, + AppleNotificationPayloadVO payloadVO) { + + } } From 60333bc097b244c52937a06ec4ccf4c11a47cdfa Mon Sep 17 00:00:00 2001 From: hyeonjeongs Date: Sun, 10 Sep 2023 16:39:34 +0900 Subject: [PATCH 2/2] =?UTF-8?q?YEL-154=20[feat]=20slack=20notification=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../purchase/controller/PurchaseNotificationController.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/yello/server/domain/purchase/controller/PurchaseNotificationController.java b/src/main/java/com/yello/server/domain/purchase/controller/PurchaseNotificationController.java index a10713fa..4b81743c 100644 --- a/src/main/java/com/yello/server/domain/purchase/controller/PurchaseNotificationController.java +++ b/src/main/java/com/yello/server/domain/purchase/controller/PurchaseNotificationController.java @@ -5,6 +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 lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -17,6 +18,7 @@ public class PurchaseNotificationController { private final PurchaseService purchaseService; @PostMapping("/v2/apple/notifications") + @SlackPurchaseNotification public BaseResponse appleNotification( @RequestBody AppleNotificationRequest request ) {