-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
✨ Feat: 영수증 검증 및 구독 상태 조회 API 구현 #219
Conversation
SubscriptionPurchase purchase = googleInAppPurchaseVerify(request.getPackageName(), request.getProductId(), request.getPurchaseToken()); | ||
|
||
// 활성된 구독 존재 여부 확인 | ||
boolean activeSubscriptionExists = subscriptionQueryAdapter.findByMemberId(member.getId()).stream() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
exists 쿼리로 변경해봐도 좋을 것 같습니다!
다량의 데이터와 함께 두 쿼리의 성능을 비교해보면 더 좋을 것 같아요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
10만개의 데이터를 기준으로 비교한 결과,
기존: 1.1ms, exists 쿼리: 0.53ms
로 약 2배 단축된 것을 확인할 수 있었습니다. 감사합니다!
@Transactional | ||
public void createSubscription(final Member member, final SubscriptionRequest.ReceiptDTO request) { | ||
try { | ||
SubscriptionPurchase purchase = googleInAppPurchaseVerify(request.getPackageName(), request.getProductId(), request.getPurchaseToken()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
외부 서버와의 네트워크 통신은 트랜잭션 밖에서 수행되면 좋을 것 같습니다!
커넥션을 오래 점유하는 등 여러 문제점이 있습니다
트랜잭션 범위를 최소화하면 좋을 것 같아요:)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
덕분에 AOP와 트랜잭션에 대해 더 알아갈 수 있었습니다. 감사합니다! 👍🏻👍🏻
서비스 레이어에서 영수증 검증 메서드(외부 API 호출)와 DB에 구독 객체를 저장하는 메서드를 하나의 메서드로 호출하려고 했는데, self-invocation 문제 때문에 복잡해지더라구요.
그래서 Controller에서 각각의 메서드를 개별적으로 호출하는 방식으로 작성해봤는데, 성훈님이 리뷰에서 의도하신 것과 일치하는지 확인 부탁드려요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
넵! 잘 반영해주셨습니다:)
public SubscriptionResponse.SubscriptionDTO getActiveSubscriptionByMemberId(Member member, final Long memberId) { | ||
validateMember(member, memberId); | ||
|
||
Subscription subscription = subscriptionQueryAdapter.findAllByMemberId(memberId).stream() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
해당 멤버의 모든 구독 정보 목록을 메모리에 들고오지 않고 처리할 수 있는 방향으로 쿼리를 고민해보셔도 좋을 것 같아요!
private final SubscriptionService subscriptionService; | ||
|
||
@Operation(summary = "06-01 Subscription 💳 영수증 검증 및 구독하기 V2", description = "결제 영수증을 검증하고, 구독 정보를 갱신하는 API입니다.") | ||
@PostMapping("/subscriptions") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/subscriptions 를 클래스 상단 RequestMapping에 포함해도 될 것 같아요!
@@ -68,7 +65,14 @@ public enum ErrorCode { | |||
BAD_LAST_MESSAGE_ROLE(HttpStatus.BAD_REQUEST, "CHATTING_003", "마지막 메시지의 역할이 user가 아닙니다."), | |||
CAN_NOT_EMPTY_CONTENT(HttpStatus.BAD_REQUEST, "CHATTING_004", "content가 비어있습니다."), | |||
NOT_FOUND_ROLE(HttpStatus.BAD_REQUEST, "CHATTING_005", "해당하는 role을 찾을 수 없습니다."), | |||
NOT_FOUND_MODEL(HttpStatus.BAD_REQUEST, "CHATTING_006", "해당하는 mode을 찾을 수 없습니다."); | |||
NOT_FOUND_MODEL(HttpStatus.BAD_REQUEST, "CHATTING_006", "해당하는 mode을 찾을 수 없습니다."), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mode -> model로 변경부탁드립니다!
이건 프로젝트 초기부터 오타로 되어있던 것 같네요 ㅜㅜ
|
초기 의도는 조회 API 호출 시 활성화된 구독에 대해서만 만료 여부를 확인하고 상태를 갱신하려고 했습니다! |
🚀 개요
Client App에서 결제한 영수증 데이터를 서버로 전달
전달받은 영수증 데이터를 각 플랫폼에 검증 요청(현재는 구글만)
googleInAppPurchaseVerify
: request로 영수증 정보 들어오면 google play 라이브러리로 검증 요청 → paymentState가 0이면 검증 성공⏳ 작업 내용
#218
📝 논의사항
구독이 만료되면 해당 객체를 삭제하는 것이 아니라, 상태를 EXPIRED로 갱신하도록 로직을 구성했습니다. 이렇게 되면 사용자와 구독의 관계가 1:N이 되는데 어떻게 생각하시는지 궁금합니다
구독 정보를 조회할 때마다 만료된 구독인지 확인하고 상태를 갱신하는 로직을 추가했는데, 스케줄링으로 추가적으로 처리하는 것에 대해 어떻게 생각하시는지 궁금합니다
IDE에서 자동으로 정렬이 되어버려서 불필요한 파일들이 수정되었는데 시간 날 때 Spotless 같은 거 도입해 봐도 좋을 것 같습니다 😅😅