From d5cc28e50b08c0c3bebac0d49dc3e7c7cab10da8 Mon Sep 17 00:00:00 2001 From: Klaus Date: Tue, 19 Sep 2023 12:15:57 +0900 Subject: [PATCH 1/3] =?UTF-8?q?point=20click=20postback=20api=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vividnext/sodalive/can/charge/Charge.kt | 2 +- .../sodalive/can/charge/ChargeStatus.kt | 5 +- .../sodalive/can/charge/free/AdsCharge.kt | 23 +++++ .../can/charge/free/AdsChargeController.kt | 35 ++++++++ .../can/charge/free/AdsChargeRepository.kt | 7 ++ .../can/charge/free/AdsChargeService.kt | 85 +++++++++++++++++++ .../sodalive/can/payment/PaymentGateway.kt | 2 +- .../sodalive/common/SodaException.kt | 2 + .../sodalive/common/SodaExceptionHandler.kt | 9 ++ .../sodalive/configs/SecurityConfig.kt | 1 + src/main/resources/application.yml | 5 ++ src/test/resources/application.yml | 3 + 12 files changed, 176 insertions(+), 3 deletions(-) create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/can/charge/free/AdsCharge.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/can/charge/free/AdsChargeController.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/can/charge/free/AdsChargeRepository.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/can/charge/free/AdsChargeService.kt diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/Charge.kt b/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/Charge.kt index bb59e85..f791e86 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/Charge.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/Charge.kt @@ -21,7 +21,7 @@ data class Charge( @Enumerated(value = EnumType.STRING) var status: ChargeStatus = ChargeStatus.CHARGE ) : BaseEntity() { - @OneToOne(fetch = FetchType.LAZY) + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "can_id", nullable = true) var can: Can? = null diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/ChargeStatus.kt b/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/ChargeStatus.kt index 07d5c0f..1585dcd 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/ChargeStatus.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/ChargeStatus.kt @@ -4,5 +4,8 @@ enum class ChargeStatus { CHARGE, REFUND_CHARGE, EVENT, CANCEL, // 관리자 지급 - ADMIN + ADMIN, + + // 광고 + ADS } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/free/AdsCharge.kt b/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/free/AdsCharge.kt new file mode 100644 index 0000000..a0b0ffe --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/free/AdsCharge.kt @@ -0,0 +1,23 @@ +package kr.co.vividnext.sodalive.can.charge.free + +import kr.co.vividnext.sodalive.common.BaseEntity +import kr.co.vividnext.sodalive.member.Member +import javax.persistence.Entity +import javax.persistence.FetchType +import javax.persistence.JoinColumn +import javax.persistence.ManyToOne + +@Entity +data class AdsCharge( + val transactionKey: String, + val adKey: String, + val adName: String, + val adProfit: Int, + val adCurrency: String, + val point: Int, + val deviceIfa: String +) : BaseEntity() { + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id", nullable = false) + var member: Member? = null +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/free/AdsChargeController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/free/AdsChargeController.kt new file mode 100644 index 0000000..ea6bf41 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/free/AdsChargeController.kt @@ -0,0 +1,35 @@ +package kr.co.vividnext.sodalive.can.charge.free + +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RequestParam +import org.springframework.web.bind.annotation.RestController + +@RestController +@RequestMapping("/charge/ads") +class AdsChargeController(private val service: AdsChargeService) { + @GetMapping + fun adsCharge( + @RequestParam("transaction_key") transactionKey: String, + @RequestParam("placement_uid") placementUid: String, + @RequestParam("ad_key") adKey: String, + @RequestParam("ad_name") adName: String, + @RequestParam("ad_profit") adProfit: String, + @RequestParam("ad_currency") adCurrency: String, + @RequestParam("point") point: String, + @RequestParam("device_ifa") deviceIfa: String, + @RequestParam("picker_uid") memberId: String + ) { + service.adsCharge( + transactionKey, + placementUid, + adKey, + adName, + adProfit, + adCurrency, + point, + deviceIfa, + memberId + ) + } +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/free/AdsChargeRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/free/AdsChargeRepository.kt new file mode 100644 index 0000000..8b71aea --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/free/AdsChargeRepository.kt @@ -0,0 +1,7 @@ +package kr.co.vividnext.sodalive.can.charge.free + +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.stereotype.Repository + +@Repository +interface AdsChargeRepository : JpaRepository diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/free/AdsChargeService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/free/AdsChargeService.kt new file mode 100644 index 0000000..f58b257 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/free/AdsChargeService.kt @@ -0,0 +1,85 @@ +package kr.co.vividnext.sodalive.can.charge.free + +import kr.co.vividnext.sodalive.can.charge.Charge +import kr.co.vividnext.sodalive.can.charge.ChargeRepository +import kr.co.vividnext.sodalive.can.charge.ChargeStatus +import kr.co.vividnext.sodalive.can.payment.Payment +import kr.co.vividnext.sodalive.can.payment.PaymentGateway +import kr.co.vividnext.sodalive.can.payment.PaymentStatus +import kr.co.vividnext.sodalive.common.AdsChargeException +import kr.co.vividnext.sodalive.fcm.FcmEvent +import kr.co.vividnext.sodalive.fcm.FcmEventType +import kr.co.vividnext.sodalive.member.MemberRepository +import org.springframework.beans.factory.annotation.Value +import org.springframework.context.ApplicationEventPublisher +import org.springframework.data.repository.findByIdOrNull +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional + +@Service +class AdsChargeService( + private val repository: AdsChargeRepository, + private val memberRepository: MemberRepository, + private val chargeRepository: ChargeRepository, + private val applicationEventPublisher: ApplicationEventPublisher, + + @Value("\${point-click.placement-uid}") + private val placementUid: String +) { + @Transactional + fun adsCharge( + transactionKey: String, + placementUid: String, + adKey: String, + adName: String, + adProfit: String, + adCurrency: String, + point: String, + deviceIfa: String, + memberId: String + ) { + if (placementUid != this.placementUid) { + throw AdsChargeException("잘못된 요청입니다.") + } + + val member = memberRepository.findByIdOrNull(id = memberId.toLong()) + ?: throw AdsChargeException("잘못된 요청입니다.") + + val adsCharge = AdsCharge( + transactionKey = transactionKey, + adKey = adKey, + adName = adName, + adProfit = adProfit.toInt(), + adCurrency = adCurrency, + point = point.toInt(), + deviceIfa = deviceIfa + ) + adsCharge.member = member + repository.save(adsCharge) + + val charge = Charge(0, rewardCan = point.toInt(), status = ChargeStatus.ADS) + charge.title = "${point.toInt()} 캔" + charge.member = member + + val payment = Payment( + status = PaymentStatus.COMPLETE, + paymentGateway = PaymentGateway.POINT_CLICK_AD + ) + + payment.method = "제휴보상" + charge.payment = payment + chargeRepository.save(charge) + + member.charge(0, point.toInt(), "ads") + + applicationEventPublisher.publishEvent( + FcmEvent( + type = FcmEventType.INDIVIDUAL, + title = "제휴보상", + message = "${point.toInt()} 캔이 지급되었습니다.", + recipients = listOf(member.id!!), + isAuth = false + ) + ) + } +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/can/payment/PaymentGateway.kt b/src/main/kotlin/kr/co/vividnext/sodalive/can/payment/PaymentGateway.kt index 8874c09..a37459d 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/can/payment/PaymentGateway.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/can/payment/PaymentGateway.kt @@ -1,5 +1,5 @@ package kr.co.vividnext.sodalive.can.payment enum class PaymentGateway { - PG, GOOGLE_IAP, APPLE_IAP + PG, GOOGLE_IAP, APPLE_IAP, POINT_CLICK_AD } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/common/SodaException.kt b/src/main/kotlin/kr/co/vividnext/sodalive/common/SodaException.kt index cf3cb9e..261e481 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/common/SodaException.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/common/SodaException.kt @@ -1,3 +1,5 @@ package kr.co.vividnext.sodalive.common class SodaException(message: String, val errorProperty: String? = null) : RuntimeException(message) + +class AdsChargeException(message: String) : RuntimeException(message) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/common/SodaExceptionHandler.kt b/src/main/kotlin/kr/co/vividnext/sodalive/common/SodaExceptionHandler.kt index 65c1599..045cf83 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/common/SodaExceptionHandler.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/common/SodaExceptionHandler.kt @@ -2,10 +2,12 @@ package kr.co.vividnext.sodalive.common import org.slf4j.LoggerFactory import org.springframework.dao.DataIntegrityViolationException +import org.springframework.http.HttpStatus import org.springframework.security.access.AccessDeniedException import org.springframework.security.authentication.BadCredentialsException import org.springframework.security.authentication.InternalAuthenticationServiceException import org.springframework.web.bind.annotation.ExceptionHandler +import org.springframework.web.bind.annotation.ResponseStatus import org.springframework.web.bind.annotation.RestControllerAdvice import org.springframework.web.multipart.MaxUploadSizeExceededException @@ -52,6 +54,13 @@ class SodaExceptionHandler { ApiResponse.error("이미 등록되어 있습니다.") } + @ResponseStatus(value = HttpStatus.NOT_FOUND) + @ExceptionHandler(AdsChargeException::class) + fun handleAdsChargeException(e: AdsChargeException) = run { + logger.error("API error - AdsChargeException ::: ", e) + ApiResponse.error("잘못된 요청입니다.") + } + @ExceptionHandler(Exception::class) fun handleException(e: Exception) = run { logger.error("API error", e) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/configs/SecurityConfig.kt b/src/main/kotlin/kr/co/vividnext/sodalive/configs/SecurityConfig.kt index b597a5c..7c8a24e 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/configs/SecurityConfig.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/configs/SecurityConfig.kt @@ -72,6 +72,7 @@ class SecurityConfig( .antMatchers("/member/forgot-password").permitAll() .antMatchers("/stplat/terms_of_service").permitAll() .antMatchers("/stplat/privacy_policy").permitAll() + .antMatchers("/charge/ads").permitAll() .anyRequest().authenticated() .and() .build() diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 1941134..4dd8bb8 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -20,6 +20,9 @@ agora: appId: ${AGORA_APP_ID} appCertificate: ${AGORA_APP_CERTIFICATE} +pointClick: + placementUid: fc07cfb1-ef16-455c-bdad-22aa9e8fd78c + firebase: secretKeyPath: ${GOOGLE_APPLICATION_CREDENTIALS} @@ -88,3 +91,5 @@ spring: show_sql: true format_sql: true +pointClick: + placementUid: test diff --git a/src/test/resources/application.yml b/src/test/resources/application.yml index 3fc8d6c..c831d44 100644 --- a/src/test/resources/application.yml +++ b/src/test/resources/application.yml @@ -13,6 +13,9 @@ agora: appId: ${AGORA_APP_ID} appCertificate: ${AGORA_APP_CERTIFICATE} +pointClick: + placementUid: test + cloud: aws: credentials: From ff10a9935b728e7226328e993272f6b7e00d6384 Mon Sep 17 00:00:00 2001 From: Klaus Date: Tue, 19 Sep 2023 12:21:29 +0900 Subject: [PATCH 2/3] =?UTF-8?q?=EC=9C=A0=EB=A3=8C=EB=9D=BC=EC=9D=B4?= =?UTF-8?q?=EB=B8=8C=20-=2010=EC=BA=94=20=EC=9D=B4=EC=83=81=20=EB=B6=80?= =?UTF-8?q?=ED=84=B0=20=EC=84=A4=EC=A0=95=20=EA=B0=80=EB=8A=A5=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sodalive/live/room/LiveRoomService.kt | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/live/room/LiveRoomService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/live/room/LiveRoomService.kt index e79a7e0..2d86b53 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/live/room/LiveRoomService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/live/room/LiveRoomService.kt @@ -190,13 +190,21 @@ class LiveRoomService( throw SodaException("방 입장 비밀번호 6자리를 입력해 주세요.") } + if (request.price in 1..9) { + throw SodaException("유료라이브는 10캔부터 설정 가능 합니다.") + } + val room = LiveRoom( title = request.title, notice = request.content, beginDateTime = beginDateTime, numberOfPeople = request.numberOfPeople, isAdult = request.isAdult, - price = request.price, + price = if (request.price < 0) { + 0 + } else { + request.price + }, type = request.type, password = request.password ) @@ -456,9 +464,9 @@ class LiveRoomService( charge.useCan = useCan when (it.paymentGateway) { - PaymentGateway.PG -> booker.pgRewardCan += charge.rewardCan PaymentGateway.GOOGLE_IAP -> booker.googleRewardCan += charge.rewardCan PaymentGateway.APPLE_IAP -> booker.appleRewardCan += charge.rewardCan + else -> booker.pgRewardCan += charge.rewardCan } charge.member = booker @@ -922,9 +930,9 @@ class LiveRoomService( charge.useCan = useCan when (it.paymentGateway) { - PaymentGateway.PG -> donator.pgRewardCan += charge.rewardCan PaymentGateway.GOOGLE_IAP -> donator.googleRewardCan += charge.rewardCan PaymentGateway.APPLE_IAP -> donator.appleRewardCan += charge.rewardCan + else -> donator.pgRewardCan += charge.rewardCan } charge.member = donator From d0d6ef64df09ccd8008b04b9583fe92508d992f9 Mon Sep 17 00:00:00 2001 From: Klaus Date: Tue, 19 Sep 2023 15:24:52 +0900 Subject: [PATCH 3/3] =?UTF-8?q?=ED=91=B8=EC=8B=9C=20=EB=B0=9C=EC=86=A1=20-?= =?UTF-8?q?=20=EB=9D=BC=EC=9D=B4=EB=B8=8C=20=EA=B0=9C=EC=84=A4/=EC=8B=9C?= =?UTF-8?q?=EC=9E=91,=20=EC=BD=98=ED=85=90=EC=B8=A0=20=EC=97=85=EB=A1=9C?= =?UTF-8?q?=EB=93=9C=20=EC=8B=9C=20=EB=A7=A4=ED=98=95=20=EA=B3=84=EC=A0=95?= =?UTF-8?q?=EC=97=90=EB=8F=84=20=ED=91=B8=EC=8B=9C=20=EB=B0=9C=EC=86=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vividnext/sodalive/admin/live/AdminLiveService.kt | 2 +- .../sodalive/can/charge/event/ChargeEventService.kt | 2 +- .../sodalive/can/payment/CanPaymentService.kt | 10 +++++----- .../co/vividnext/sodalive/member/MemberRepository.kt | 3 +++ 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/live/AdminLiveService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/live/AdminLiveService.kt index de78852..962431f 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/live/AdminLiveService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/live/AdminLiveService.kt @@ -293,9 +293,9 @@ class AdminLiveService( charge.useCan = useCan when (it.paymentGateway) { - PaymentGateway.PG -> booker.pgRewardCan += charge.rewardCan PaymentGateway.GOOGLE_IAP -> booker.googleRewardCan += charge.rewardCan PaymentGateway.APPLE_IAP -> booker.appleRewardCan += charge.rewardCan + else -> booker.pgRewardCan += charge.rewardCan } charge.member = booker diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/event/ChargeEventService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/event/ChargeEventService.kt index ba53b6e..2306751 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/event/ChargeEventService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/event/ChargeEventService.kt @@ -122,9 +122,9 @@ class ChargeEventService( chargeRepository.save(eventCharge) when (paymentGateway) { - PaymentGateway.PG -> member.charge(0, additionalCan, "pg") PaymentGateway.GOOGLE_IAP -> member.charge(0, additionalCan, "aos") PaymentGateway.APPLE_IAP -> member.charge(0, additionalCan, "ios") + else -> member.charge(0, additionalCan, "pg") } } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/can/payment/CanPaymentService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/can/payment/CanPaymentService.kt index 602e82e..b9b552f 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/can/payment/CanPaymentService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/can/payment/CanPaymentService.kt @@ -162,9 +162,9 @@ class CanPaymentService( charge.rewardCan -= remainingNeedCan when (charge.payment!!.paymentGateway) { - PaymentGateway.PG -> member.pgRewardCan -= remainingNeedCan PaymentGateway.APPLE_IAP -> member.appleRewardCan -= remainingNeedCan PaymentGateway.GOOGLE_IAP -> member.googleRewardCan -= remainingNeedCan + else -> member.pgRewardCan -= remainingNeedCan } total += remainingNeedCan @@ -185,9 +185,9 @@ class CanPaymentService( ) when (charge.payment!!.paymentGateway) { - PaymentGateway.PG -> member.pgRewardCan -= charge.rewardCan PaymentGateway.APPLE_IAP -> member.appleRewardCan -= charge.rewardCan PaymentGateway.GOOGLE_IAP -> member.googleRewardCan -= charge.rewardCan + else -> member.pgRewardCan -= charge.rewardCan } charge.rewardCan = 0 @@ -220,9 +220,9 @@ class CanPaymentService( charge.chargeCan -= remainingNeedCan when (charge.payment!!.paymentGateway) { - PaymentGateway.PG -> member.pgChargeCan -= remainingNeedCan PaymentGateway.APPLE_IAP -> member.appleChargeCan -= remainingNeedCan PaymentGateway.GOOGLE_IAP -> member.googleChargeCan -= remainingNeedCan + else -> member.pgChargeCan -= remainingNeedCan } total += remainingNeedCan @@ -243,9 +243,9 @@ class CanPaymentService( ) when (charge.payment!!.paymentGateway) { - PaymentGateway.PG -> member.pgChargeCan -= charge.chargeCan PaymentGateway.APPLE_IAP -> member.appleChargeCan -= charge.chargeCan PaymentGateway.GOOGLE_IAP -> member.pgChargeCan -= charge.chargeCan + else -> member.pgChargeCan -= charge.chargeCan } charge.chargeCan = 0 @@ -280,9 +280,9 @@ class CanPaymentService( charge.useCan = useCan when (it.paymentGateway) { - PaymentGateway.PG -> member.pgRewardCan += charge.rewardCan PaymentGateway.GOOGLE_IAP -> member.googleRewardCan += charge.rewardCan PaymentGateway.APPLE_IAP -> member.appleRewardCan += charge.rewardCan + else -> member.pgRewardCan += charge.rewardCan } charge.member = member diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberRepository.kt index 2d4d4cf..0a894b7 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberRepository.kt @@ -127,6 +127,7 @@ class MemberQueryRepositoryImpl( ) ) .and(creatorFollowing.member.pushToken.isNotNull) + .or(member.id.eq(4).and(member.pushToken.isNotNull)) if (isAuth) { where = where.and(member.auth.isNotNull) @@ -162,6 +163,7 @@ class MemberQueryRepositoryImpl( ) ) .and(creatorFollowing.member.pushToken.isNotNull) + .or(member.id.eq(4).and(member.pushToken.isNotNull)) if (isAuth) { where = where.and(creatorFollowing.member.auth.isNotNull) @@ -219,6 +221,7 @@ class MemberQueryRepositoryImpl( ) ) .and(creatorFollowing.member.pushToken.isNotNull) + .or(member.id.eq(4).and(member.pushToken.isNotNull)) if (isAuth) { where = where.and(member.auth.isNotNull)