Skip to content

Commit

Permalink
Merge pull request #484 from team-yello/staging
Browse files Browse the repository at this point in the history
[deploy] 2.0.3v
  • Loading branch information
euije authored Mar 25, 2024
2 parents 88a2577 + 1aa5e7c commit fa222e9
Show file tree
Hide file tree
Showing 35 changed files with 1,129 additions and 512 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ dependencies {
implementation 'com.google.firebase:firebase-admin:9.2.0'

// slack-webhook
implementation "net.gpedro.integrations.slack:slack-webhook:1.4.0"
implementation "com.slack.api:slack-api-client:1.38.3"

// google play android developer api
implementation 'com.google.apis:google-api-services-androidpublisher:v3-rev20211125-1.32.1'
Expand Down
1 change: 1 addition & 0 deletions lombok.config
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
lombok.copyableAnnotations += org.springframework.beans.factory.annotation.Qualifier
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@
import com.yello.server.domain.group.entity.UserGroupType;
import com.yello.server.global.common.annotation.ServiceToken;
import com.yello.server.global.common.dto.BaseResponse;
import com.yello.server.infrastructure.slack.annotation.SlackSignUpNotification;
import com.yello.server.infrastructure.slack.dto.response.SlackChannel;
import com.yello.server.infrastructure.slack.service.SlackService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
Expand All @@ -42,6 +44,7 @@
public class AuthController {

private final AuthService authService;
private final SlackService slackService;

@PostMapping("/oauth")
public BaseResponse<OAuthResponse> oauthLogin(@RequestBody OAuthRequest oAuthRequest) {
Expand All @@ -56,10 +59,10 @@ public BaseResponse<Boolean> getYelloIdValidation(@RequestParam("yelloId") Strin
}

@PostMapping("/signup")
@SlackSignUpNotification
public BaseResponse<SignUpResponse> postSignUp(
@Valid @RequestBody SignUpRequest signUpRequest) {
@Valid @RequestBody SignUpRequest signUpRequest, HttpServletRequest servletRequest) throws Exception {
val data = authService.signUp(signUpRequest);
slackService.sendSignUpMessage(SlackChannel.SIGN_UP, servletRequest);
return BaseResponse.success(SIGN_UP_SUCCESS, data);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,14 @@
import com.yello.server.domain.purchase.dto.response.GoogleTicketGetResponse;
import com.yello.server.domain.purchase.dto.response.UserPurchaseInfoResponse;
import com.yello.server.domain.purchase.dto.response.UserSubscribeNeededResponse;
import com.yello.server.domain.purchase.entity.Purchase;
import com.yello.server.domain.purchase.service.PurchaseService;
import com.yello.server.domain.user.entity.User;
import com.yello.server.global.common.annotation.AccessTokenUser;
import com.yello.server.global.common.dto.BaseResponse;
import com.yello.server.infrastructure.slack.annotation.SlackPurchaseNotification;
import com.yello.server.infrastructure.slack.dto.response.SlackChannel;
import com.yello.server.infrastructure.slack.service.SlackService;
import jakarta.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.time.LocalDateTime;
import lombok.RequiredArgsConstructor;
Expand All @@ -36,44 +39,57 @@
public class PurchaseController {

private final PurchaseService purchaseService;
private final SlackService slackService;

@PostMapping("/apple/verify/subscribe")
@SlackPurchaseNotification
public BaseResponse verifyAppleSubscriptionTransaction(
@RequestBody AppleTransaction appleTransaction,
@AccessTokenUser User user
) {
@AccessTokenUser User user,
HttpServletRequest servletRequest
) throws IOException {
purchaseService.verifyAppleSubscriptionTransaction(user.getId(), appleTransaction);
final Purchase purchase = purchaseService.getByTransactionId(appleTransaction.transactionId());

slackService.sendPurchaseMessage(SlackChannel.PURCHASE, servletRequest, purchase);
return BaseResponse.success(VERIFY_RECEIPT_SUCCESS);
}

@PostMapping("/apple/verify/ticket")
@SlackPurchaseNotification
public BaseResponse verifyAppleTicketTransaction(
@RequestBody AppleTransaction appleTransaction,
@AccessTokenUser User user
) {
@AccessTokenUser User user,
HttpServletRequest servletRequest
) throws IOException {
purchaseService.verifyAppleTicketTransaction(user.getId(), appleTransaction);
final Purchase purchase = purchaseService.getByTransactionId(appleTransaction.transactionId());

slackService.sendPurchaseMessage(SlackChannel.PURCHASE, servletRequest, purchase);
return BaseResponse.success(VERIFY_RECEIPT_SUCCESS);
}

@PostMapping("/google/verify/subscribe")
@SlackPurchaseNotification
public BaseResponse<GoogleSubscriptionGetResponse> verifyGoogleSubscriptionTransaction(
@AccessTokenUser User user,
@RequestBody GoogleSubscriptionGetRequest request
@RequestBody GoogleSubscriptionGetRequest request,
HttpServletRequest servletRequest
) throws IOException {
val data = purchaseService.verifyGoogleSubscriptionTransaction(user.getId(), request);
final Purchase purchase = purchaseService.getByTransactionId(request.orderId());

slackService.sendPurchaseMessage(SlackChannel.PURCHASE, servletRequest, purchase);
return BaseResponse.success(GOOGLE_PURCHASE_SUBSCRIPTION_VERIFY_SUCCESS, data);
}

@PostMapping("/google/verify/ticket")
@SlackPurchaseNotification
public BaseResponse<GoogleTicketGetResponse> verifyGoogleTicketTransaction(
@AccessTokenUser User user,
@RequestBody GoogleTicketGetRequest request
@RequestBody GoogleTicketGetRequest request,
HttpServletRequest servletRequest
) throws IOException {
val data = purchaseService.verifyGoogleTicketTransaction(user.getId(), request);
final Purchase purchase = purchaseService.getByTransactionId(request.orderId());

slackService.sendPurchaseMessage(SlackChannel.PURCHASE, servletRequest, purchase);
return BaseResponse.success(GOOGLE_PURCHASE_INAPP_VERIFY_SUCCESS, data);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,18 @@

import com.yello.server.domain.purchase.dto.request.AppleNotificationRequest;
import com.yello.server.domain.purchase.dto.request.GooglePubSubNotificationRequest;
import com.yello.server.domain.purchase.dto.request.google.DeveloperNotification;
import com.yello.server.domain.purchase.entity.Purchase;
import com.yello.server.domain.purchase.service.PurchaseService;
import com.yello.server.global.common.dto.BaseResponse;
import com.yello.server.global.common.dto.EmptyObject;
import com.yello.server.infrastructure.slack.annotation.SlackApplePurchaseNotification;
import com.yello.server.infrastructure.slack.dto.response.SlackChannel;
import com.yello.server.infrastructure.slack.service.SlackService;
import jakarta.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Map;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
Expand All @@ -21,21 +29,25 @@
public class PurchaseNotificationController {

private final PurchaseService purchaseService;
private final SlackService slackService;

@PostMapping("/v2/apple/notifications")
@SlackApplePurchaseNotification
public BaseResponse appleNotification(
@RequestBody AppleNotificationRequest request
) {
public BaseResponse appleNotification(@RequestBody AppleNotificationRequest request,
HttpServletRequest servletRequest) throws IOException, URISyntaxException {
purchaseService.appleNotification(request);

slackService.sendAppleStateChangedMessage(SlackChannel.PURCHASE, servletRequest);
return BaseResponse.success(POST_APPLE_NOTIFICATION_SUCCESS);
}

@PostMapping("/v2/google/notifications")
public BaseResponse<EmptyObject> googleNotification(
@RequestBody GooglePubSubNotificationRequest request
) {
purchaseService.googleNotification(request);
@RequestBody GooglePubSubNotificationRequest request, HttpServletRequest servletRequest
) throws IOException, URISyntaxException {
final Map.Entry<DeveloperNotification, Optional<Purchase>> notification = purchaseService.googleNotification(
request);

slackService.sendGoogleStateChangedMessage(SlackChannel.PURCHASE, servletRequest, notification);
return BaseResponse.success(POST_GOOGLE_NOTIFICATION_SUCCESS, EmptyObject.builder().build());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ public interface PurchaseRepository {

Optional<Purchase> findByTransactionId(String transactionId);

Purchase getByTransactionId(String transactionId);

Optional<Purchase> findByPurchaseToken(String purchaseToken);

List<Purchase> findAllByUser(User user);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package com.yello.server.domain.purchase.repository;

import static com.yello.server.global.common.ErrorCode.NOT_EQUAL_TRANSACTION_EXCEPTION;
import static com.yello.server.global.common.ErrorCode.NOT_FOUND_USER_SUBSCRIBE_EXCEPTION;

import com.yello.server.domain.purchase.entity.ProductType;
import com.yello.server.domain.purchase.entity.Purchase;
import com.yello.server.domain.purchase.exception.PurchaseNotFoundException;
import com.yello.server.domain.user.entity.User;
import com.yello.server.global.common.ErrorCode;
import java.util.List;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
Expand All @@ -33,6 +33,12 @@ public Optional<Purchase> findByTransactionId(String transactionId) {
return purchaseJpaRepository.findByTransactionId(transactionId);
}

@Override
public Purchase getByTransactionId(String transactionId) {
return purchaseJpaRepository.findByTransactionId(transactionId)
.orElseThrow(() -> new PurchaseNotFoundException(NOT_EQUAL_TRANSACTION_EXCEPTION));
}

@Override
public Optional<Purchase> findByPurchaseToken(String purchaseToken) {
return purchaseJpaRepository.findByPurchaseToken(purchaseToken);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,16 @@
import static com.yello.server.global.common.ErrorCode.NOT_FOUND_TRANSACTION_EXCEPTION;
import static com.yello.server.global.common.ErrorCode.PURCHASE_TOKEN_NOT_FOUND_PURCHASE_EXCEPTION;
import static com.yello.server.global.common.ErrorCode.SUBSCRIBE_ACTIVE_EXCEPTION;
import static com.yello.server.global.common.util.ConstantUtil.*;
import static com.yello.server.global.common.util.ConstantUtil.APPLE_NOTIFICATION_DID_RENEW;
import static com.yello.server.global.common.util.ConstantUtil.APPLE_NOTIFICATION_EXPIRED;
import static com.yello.server.global.common.util.ConstantUtil.APPLE_NOTIFICATION_REFUND;
import static com.yello.server.global.common.util.ConstantUtil.APPLE_NOTIFICATION_SUBSCRIBED;
import static com.yello.server.global.common.util.ConstantUtil.APPLE_NOTIFICATION_SUBSCRIPTION_STATUS_CHANGE;
import static com.yello.server.global.common.util.ConstantUtil.APPLE_NOTIFICATION_TEST;
import static com.yello.server.global.common.util.ConstantUtil.FIVE_TICKET_ID;
import static com.yello.server.global.common.util.ConstantUtil.ONE_TICKET_ID;
import static com.yello.server.global.common.util.ConstantUtil.TWO_TICKET_ID;
import static com.yello.server.global.common.util.ConstantUtil.YELLO_PLUS_ID;

import com.google.gson.Gson;
import com.google.gson.JsonObject;
Expand Down Expand Up @@ -64,6 +73,7 @@
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Base64;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import lombok.Builder;
Expand Down Expand Up @@ -330,7 +340,7 @@ public void appleNotification(AppleNotificationRequest request) {
case APPLE_NOTIFICATION_SUBSCRIPTION_STATUS_CHANGE -> {
purchaseManager.changeSubscriptionStatus(payloadVO);
}
case APPLE_NOTIFICATION_EXPIRED ->{
case APPLE_NOTIFICATION_EXPIRED -> {
purchaseManager.expiredSubscribe(payloadVO);
}
case APPLE_NOTIFICATION_REFUND -> {
Expand All @@ -349,7 +359,8 @@ public void appleNotification(AppleNotificationRequest request) {
}

@Transactional
public void googleNotification(GooglePubSubNotificationRequest request) {
public Map.Entry<DeveloperNotification, Optional<Purchase>> googleNotification(
GooglePubSubNotificationRequest request) {
if (!Objects.equals(request.subscription(), googlePubSubName)) {
log.info("BAD REQUEST by wrong pub-sub name");
throw new GoogleBadRequestException(GOOGLE_NOTIFICATION_BAD_REQUEST_EXCEPTION);
Expand All @@ -363,6 +374,7 @@ public void googleNotification(GooglePubSubNotificationRequest request) {
);

final DeveloperNotification developerNotification = gson.fromJson(data, DeveloperNotification.class);
Optional<Purchase> purchase = Optional.empty();

if (ObjectUtils.isEmpty(developerNotification.getProductType())) {
log.info("BAD REQUEST by wrong pub-sub name");
Expand All @@ -374,10 +386,9 @@ public void googleNotification(GooglePubSubNotificationRequest request) {

case TEST -> {
log.info("TEST notification is sent by Google Play Console");
return;
}
case YELLO_PLUS -> {
final Optional<Purchase> purchase = purchaseRepository.findByPurchaseToken(
purchase = purchaseRepository.findByPurchaseToken(
developerNotification.subscriptionNotification().purchaseToken());

if (purchase.isEmpty()) {
Expand Down Expand Up @@ -414,12 +425,11 @@ public void googleNotification(GooglePubSubNotificationRequest request) {
}
case SUBSCRIPTION_PRICE_CHANGE_CONFIRMED -> {
// NOTHING
return;
}
}
}
case ONE_TICKET, TWO_TICKET, FIVE_TICKET -> {
final Optional<Purchase> purchase = purchaseRepository.findByPurchaseToken(
purchase = purchaseRepository.findByPurchaseToken(
developerNotification.oneTimeProductNotification().purchaseToken());

if (purchase.isEmpty()) {
Expand All @@ -445,5 +455,10 @@ public void googleNotification(GooglePubSubNotificationRequest request) {
}
}
}
return Map.entry(developerNotification, purchase);
}

public Purchase getByTransactionId(String transactionId) {
return purchaseRepository.getByTransactionId(transactionId);
}
}
12 changes: 12 additions & 0 deletions src/main/java/com/yello/server/domain/statistics/dto/SignUpVO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.yello.server.domain.statistics.dto;

import lombok.Builder;

@Builder
public record SignUpVO(
Long count,
Long maleCount,
Long femaleCount
) {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.yello.server.domain.statistics.entity;

import com.yello.server.domain.statistics.dto.SignUpVO;
import com.yello.server.global.common.entity.JsonConverter;
import com.yello.server.global.common.entity.ZonedDateTimeConverter;
import jakarta.persistence.Column;
import jakarta.persistence.Convert;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import java.time.ZonedDateTime;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import org.hibernate.annotations.DynamicInsert;

@Entity
@Getter
@SuperBuilder
@DynamicInsert
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class StatisticsDaily {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(nullable = false)
@Convert(converter = ZonedDateTimeConverter.class)
private ZonedDateTime startAt;

@Column(nullable = false)
@Convert(converter = ZonedDateTimeConverter.class)
private ZonedDateTime endAt;

/**
* json
*/
@Column
@Convert(converter = JsonConverter.class)
private SignUpVO signUp;

/**
* json
*/
@Column
private String revenue;

/**
* json
*/
@Column
private String vote;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.yello.server.domain.statistics.repository;

import com.yello.server.domain.statistics.entity.StatisticsDaily;
import org.springframework.data.jpa.repository.JpaRepository;

public interface StatisticsDailyJpaRepository extends JpaRepository<StatisticsDaily, Long> {

}
Loading

0 comments on commit fa222e9

Please sign in to comment.