diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/AdminCalculateQueryRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/AdminCalculateQueryRepository.kt index ac92331..a4d25f3 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/AdminCalculateQueryRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/AdminCalculateQueryRepository.kt @@ -122,12 +122,15 @@ class AdminCalculateQueryRepository(private val queryFactory: JPAQueryFactory) { order.type, order.can, order.id.count(), - order.can.sum() + order.can.sum(), + creatorSettlementRatio.contentSettlementRatio ) ) .from(order) .innerJoin(order.audioContent, audioContent) .innerJoin(audioContent.member, member) + .leftJoin(creatorSettlementRatio) + .on(member.id.eq(creatorSettlementRatio.member.id)) .where(order.isActive.isTrue) .groupBy(member.id, audioContent.id, order.type, order.can) .offset(offset) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/GetCalculateCommunityPostQueryData.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/GetCalculateCommunityPostQueryData.kt index 4bd63db..009eeb9 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/GetCalculateCommunityPostQueryData.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/GetCalculateCommunityPostQueryData.kt @@ -1,7 +1,8 @@ package kr.co.vividnext.sodalive.admin.calculate import com.querydsl.core.annotations.QueryProjection -import kotlin.math.roundToInt +import java.math.BigDecimal +import java.math.RoundingMode data class GetCalculateCommunityPostQueryData @QueryProjection constructor( val nickname: String, @@ -13,15 +14,24 @@ data class GetCalculateCommunityPostQueryData @QueryProjection constructor( val settlementRatio: Int? ) { fun toGetCalculateCommunityPostResponse(): GetCalculateCommunityPostResponse { - val totalKrw = totalCan * 100 - val paymentFee = totalKrw * 0.066f + // 원화 = totalCoin * 100 ( 캔 1개 = 100원 ) + val totalKrw = BigDecimal(totalCan).multiply(BigDecimal(100)) + + // 결제수수료 : 6.6% + val paymentFee = totalKrw.multiply(BigDecimal(0.066)) + + // 정산금액 = (원화 - 결제수수료) 의 70% val settlementAmount = if (settlementRatio != null) { - (totalKrw.toFloat() - paymentFee) * (settlementRatio.toFloat() / 100.0f) + totalKrw.subtract(paymentFee).multiply(BigDecimal(settlementRatio).divide(BigDecimal(100.0))) } else { - (totalKrw.toFloat() - paymentFee) * 0.7f + totalKrw.subtract(paymentFee).multiply(BigDecimal(0.7)) } - val tax = settlementAmount * 0.033 - val depositAmount = settlementAmount - tax + + // 원천세 = 정산금액의 3.3% + val tax = settlementAmount.multiply(BigDecimal(0.033)) + + // 입금액 + val depositAmount = settlementAmount.subtract(tax) return GetCalculateCommunityPostResponse( nickname = nickname, @@ -30,11 +40,11 @@ data class GetCalculateCommunityPostQueryData @QueryProjection constructor( can = can, numberOfPurchase = numberOfPurchase.toInt(), totalCan = totalCan, - totalKrw = totalKrw, - paymentFee = paymentFee.roundToInt(), - settlementAmount = settlementAmount.roundToInt(), - tax = tax.roundToInt(), - depositAmount = depositAmount.roundToInt() + totalKrw = totalKrw.toInt(), + paymentFee = paymentFee.setScale(0, RoundingMode.HALF_UP).toInt(), + settlementAmount = settlementAmount.setScale(0, RoundingMode.HALF_UP).toInt(), + tax = tax.setScale(0, RoundingMode.HALF_UP).toInt(), + depositAmount = depositAmount.setScale(0, RoundingMode.HALF_UP).toInt() ) } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/GetCalculateContentDonationQueryData.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/GetCalculateContentDonationQueryData.kt index 77ed086..22651a8 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/GetCalculateContentDonationQueryData.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/GetCalculateContentDonationQueryData.kt @@ -1,7 +1,8 @@ package kr.co.vividnext.sodalive.admin.calculate import com.querydsl.core.annotations.QueryProjection -import kotlin.math.roundToInt +import java.math.BigDecimal +import java.math.RoundingMode data class GetCalculateContentDonationQueryData @QueryProjection constructor( // 등록 크리에이터 닉네임 @@ -21,25 +22,25 @@ data class GetCalculateContentDonationQueryData @QueryProjection constructor( ) { fun toGetCalculateContentDonationResponse(): GetCalculateContentDonationResponse { // 원화 = totalCoin * 100 ( 캔 1개 = 100원 ) - val totalKrw = totalCan * 100 + val totalKrw = BigDecimal(totalCan).multiply(BigDecimal(100)) // 결제수수료 : 6.6% - val paymentFee = totalKrw * 0.066f + val paymentFee = totalKrw.multiply(BigDecimal(0.066)) // 정산금액 // 유료콘텐츠 (원화 - 결제수수료) 의 90% // 무료콘텐츠 (원화 - 결제수수료) 의 70% val settlementAmount = if (price > 0) { - (totalKrw.toFloat() - paymentFee) * 0.9 + totalKrw.subtract(paymentFee).multiply(BigDecimal(0.9)) } else { - (totalKrw.toFloat() - paymentFee) * 0.7 + totalKrw.subtract(paymentFee).multiply(BigDecimal(0.7)) } // 원천세 = 정산금액의 3.3% - val tax = settlementAmount * 0.033 + val tax = settlementAmount.multiply(BigDecimal(0.033)) // 입금액 - val depositAmount = settlementAmount - tax + val depositAmount = settlementAmount.subtract(tax) val paidOrFree = if (price > 0) { "유료" @@ -55,11 +56,11 @@ data class GetCalculateContentDonationQueryData @QueryProjection constructor( donationDate = donationDate, numberOfDonation = numberOfDonation.toInt(), totalCan = totalCan, - totalKrw = totalKrw, - paymentFee = paymentFee.roundToInt(), - settlementAmount = settlementAmount.roundToInt(), - tax = tax.roundToInt(), - depositAmount = depositAmount.roundToInt() + totalKrw = totalKrw.toInt(), + paymentFee = paymentFee.setScale(0, RoundingMode.HALF_UP).toInt(), + settlementAmount = settlementAmount.setScale(0, RoundingMode.HALF_UP).toInt(), + tax = tax.setScale(0, RoundingMode.HALF_UP).toInt(), + depositAmount = depositAmount.setScale(0, RoundingMode.HALF_UP).toInt() ) } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/GetCalculateContentQueryData.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/GetCalculateContentQueryData.kt index b886d53..cf0a0c6 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/GetCalculateContentQueryData.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/GetCalculateContentQueryData.kt @@ -2,7 +2,8 @@ package kr.co.vividnext.sodalive.admin.calculate import com.querydsl.core.annotations.QueryProjection import kr.co.vividnext.sodalive.content.order.OrderType -import kotlin.math.roundToInt +import java.math.BigDecimal +import java.math.RoundingMode data class GetCalculateContentQueryData @QueryProjection constructor( // 등록 크리에이터 닉네임 @@ -32,23 +33,22 @@ data class GetCalculateContentQueryData @QueryProjection constructor( } // 원화 = totalCoin * 100 ( 캔 1개 = 100원 ) - val totalKrw = totalCan * 100 + val totalKrw = BigDecimal(totalCan).multiply(BigDecimal(100)) // 결제수수료 : 6.6% - val paymentFee = totalKrw * 0.066f + val paymentFee = totalKrw.multiply(BigDecimal(0.066)) // 정산금액 = (원화 - 결제수수료) 의 70% val settlementAmount = if (settlementRatio != null) { - (totalKrw.toFloat() - paymentFee) * (settlementRatio.toFloat() / 100.0f) + totalKrw.subtract(paymentFee).multiply(BigDecimal(settlementRatio).divide(BigDecimal(100.0))) } else { - (totalKrw.toFloat() - paymentFee) * 0.7f + totalKrw.subtract(paymentFee).multiply(BigDecimal(0.7)) } // 원천세 = 정산금액의 3.3% - val tax = settlementAmount * 0.033 + val tax = settlementAmount.multiply(BigDecimal(0.033)) - // 입금액 - val depositAmount = settlementAmount - tax + val depositAmount = settlementAmount.subtract(tax) return GetCalculateContentResponse( nickname = nickname, @@ -59,11 +59,11 @@ data class GetCalculateContentQueryData @QueryProjection constructor( orderPrice = orderPrice, numberOfPeople = numberOfPeople.toInt(), totalCan = totalCan, - totalKrw = totalKrw, - paymentFee = paymentFee.roundToInt(), - settlementAmount = settlementAmount.roundToInt(), - tax = tax.roundToInt(), - depositAmount = depositAmount.roundToInt() + totalKrw = totalKrw.toInt(), + paymentFee = paymentFee.setScale(0, RoundingMode.HALF_UP).toInt(), + settlementAmount = settlementAmount.setScale(0, RoundingMode.HALF_UP).toInt(), + tax = tax.setScale(0, RoundingMode.HALF_UP).toInt(), + depositAmount = depositAmount.setScale(0, RoundingMode.HALF_UP).toInt() ) } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/GetCalculateLiveQueryData.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/GetCalculateLiveQueryData.kt index d372c7f..41b6515 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/GetCalculateLiveQueryData.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/GetCalculateLiveQueryData.kt @@ -2,7 +2,8 @@ package kr.co.vividnext.sodalive.admin.calculate import com.querydsl.core.annotations.QueryProjection import kr.co.vividnext.sodalive.can.use.CanUsage -import kotlin.math.roundToInt +import java.math.BigDecimal +import java.math.RoundingMode data class GetCalculateLiveQueryData @QueryProjection constructor( val email: String, @@ -42,23 +43,23 @@ data class GetCalculateLiveQueryData @QueryProjection constructor( } // 원화 = totalCoin * 100 ( 캔 1개 = 100원 ) - val totalKrw = totalAmount * 100 + val totalKrw = BigDecimal(totalAmount).multiply(BigDecimal(100)) // 결제수수료 : 6.6% - val paymentFee = totalKrw * 0.066f + val paymentFee = totalKrw.multiply(BigDecimal(0.066)) // 정산금액 = (원화 - 결제수수료) 의 70% val settlementAmount = if (settlementRatio != null) { - (totalKrw.toFloat() - paymentFee) * (settlementRatio.toFloat() / 100.0f) + totalKrw.subtract(paymentFee).multiply(BigDecimal(settlementRatio).divide(BigDecimal(100.0))) } else { - (totalKrw.toFloat() - paymentFee) * 0.7f + totalKrw.subtract(paymentFee).multiply(BigDecimal(0.7)) } // 원천세 = 정산금액의 3.3% - val tax = settlementAmount * 0.033 + val tax = settlementAmount.multiply(BigDecimal(0.033)) // 입금액 - val depositAmount = settlementAmount - tax + val depositAmount = settlementAmount.subtract(tax) return GetCalculateLiveResponse( email = email, @@ -69,11 +70,11 @@ data class GetCalculateLiveQueryData @QueryProjection constructor( canUsageStr = canUsageStr, numberOfPeople = numberOfPeople, totalAmount = totalAmount, - totalKrw = totalKrw, - paymentFee = paymentFee.roundToInt(), - settlementAmount = settlementAmount.roundToInt(), - tax = tax.roundToInt(), - depositAmount = depositAmount.roundToInt() + totalKrw = totalKrw.toInt(), + paymentFee = paymentFee.setScale(0, RoundingMode.HALF_UP).toInt(), + settlementAmount = settlementAmount.setScale(0, RoundingMode.HALF_UP).toInt(), + tax = tax.setScale(0, RoundingMode.HALF_UP).toInt(), + depositAmount = depositAmount.setScale(0, RoundingMode.HALF_UP).toInt() ) } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/GetCumulativeSalesByContentResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/GetCumulativeSalesByContentResponse.kt index ac2a48c..5c49858 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/GetCumulativeSalesByContentResponse.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/GetCumulativeSalesByContentResponse.kt @@ -3,7 +3,8 @@ package kr.co.vividnext.sodalive.admin.calculate import com.fasterxml.jackson.annotation.JsonProperty import com.querydsl.core.annotations.QueryProjection import kr.co.vividnext.sodalive.content.order.OrderType -import kotlin.math.roundToInt +import java.math.BigDecimal +import java.math.RoundingMode data class GetCumulativeSalesByContentQueryData @QueryProjection constructor( // 등록 크리에이터 닉네임 @@ -19,7 +20,9 @@ data class GetCumulativeSalesByContentQueryData @QueryProjection constructor( // 인원 val numberOfPeople: Long, // 합계 - val totalCan: Int + val totalCan: Int, + // 정산비율 + val settlementRatio: Int? ) { fun toCumulativeSalesByContentItem(): CumulativeSalesByContentItem { val orderTypeStr = if (orderType == OrderType.RENTAL) { @@ -29,19 +32,23 @@ data class GetCumulativeSalesByContentQueryData @QueryProjection constructor( } // 원화 = totalCoin * 100 ( 캔 1개 = 100원 ) - val totalKrw = totalCan * 100 + val totalKrw = BigDecimal(totalCan).multiply(BigDecimal(100)) // 결제수수료 : 6.6% - val paymentFee = totalKrw * 0.066f + val paymentFee = totalKrw.multiply(BigDecimal(0.066)) // 정산금액 = (원화 - 결제수수료) 의 70% - val settlementAmount = (totalKrw.toFloat() - paymentFee) * 0.7 + val settlementAmount = if (settlementRatio != null) { + totalKrw.subtract(paymentFee).multiply(BigDecimal(settlementRatio).divide(BigDecimal(100.0))) + } else { + totalKrw.subtract(paymentFee).multiply(BigDecimal(0.7)) + } // 원천세 = 정산금액의 3.3% - val tax = settlementAmount * 0.033 + val tax = settlementAmount.multiply(BigDecimal(0.033)) // 입금액 - val depositAmount = settlementAmount - tax + val depositAmount = settlementAmount.subtract(tax) return CumulativeSalesByContentItem( nickname = nickname, @@ -51,11 +58,11 @@ data class GetCumulativeSalesByContentQueryData @QueryProjection constructor( orderPrice = orderPrice, numberOfPeople = numberOfPeople.toInt(), totalCan = totalCan, - totalKrw = totalKrw, - paymentFee = paymentFee.roundToInt(), - settlementAmount = settlementAmount.roundToInt(), - tax = tax.roundToInt(), - depositAmount = depositAmount.roundToInt() + totalKrw = totalKrw.toInt(), + paymentFee = paymentFee.setScale(0, RoundingMode.HALF_UP).toInt(), + settlementAmount = settlementAmount.setScale(0, RoundingMode.HALF_UP).toInt(), + tax = tax.setScale(0, RoundingMode.HALF_UP).toInt(), + depositAmount = depositAmount.setScale(0, RoundingMode.HALF_UP).toInt() ) } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/ChargeController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/ChargeController.kt index 53c0eca..cd6b8da 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/ChargeController.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/ChargeController.kt @@ -33,6 +33,12 @@ class ChargeController(private val service: ChargeService) { @AuthenticationPrincipal user: User ) = ApiResponse.ok(service.verify(user, verifyRequest)) + @PostMapping("/verify/hecto") + fun verifyHecto( + @RequestBody verifyRequest: VerifyRequest, + @AuthenticationPrincipal user: User + ) = ApiResponse.ok(service.verifyHecto(user, verifyRequest)) + @PostMapping("/apple") fun appleCharge( @RequestBody chargeRequest: AppleChargeRequest, diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/ChargeService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/ChargeService.kt index 57bf8a9..f65c389 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/ChargeService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/ChargeService.kt @@ -45,6 +45,10 @@ class ChargeService( private val bootpayApplicationId: String, @Value("\${bootpay.private-key}") private val bootpayPrivateKey: String, + @Value("\${bootpay.hecto-application-id}") + private val bootpayHectoApplicationId: String, + @Value("\${bootpay.hecto-private-key}") + private val bootpayHectoPrivateKey: String, @Value("\${apple.iap-verify-sandbox-url}") private val appleInAppVerifySandBoxUrl: String, @Value("\${apple.iap-verify-url}") @@ -137,6 +141,46 @@ class ChargeService( } } + @Transactional + fun verifyHecto(user: User, verifyRequest: VerifyRequest) { + val charge = chargeRepository.findByIdOrNull(verifyRequest.orderId.toLong()) + ?: throw SodaException("결제정보에 오류가 있습니다.") + val member = memberRepository.findByEmail(user.username) + ?: throw SodaException("로그인 정보를 확인해주세요.") + + if (charge.payment!!.paymentGateway == PaymentGateway.PG) { + val bootpay = Bootpay(bootpayHectoApplicationId, bootpayHectoPrivateKey) + + try { + bootpay.accessToken + val verifyResult = objectMapper.convertValue( + bootpay.getReceipt(verifyRequest.receiptId), + VerifyResult::class.java + ) + + if (verifyResult.status == 1 && verifyResult.price == charge.can?.price) { + charge.payment?.receiptId = verifyResult.receiptId + charge.payment?.method = verifyResult.method + charge.payment?.status = PaymentStatus.COMPLETE + member.charge(charge.chargeCan, charge.rewardCan, "pg") + + applicationEventPublisher.publishEvent( + ChargeSpringEvent( + chargeId = charge.id!!, + memberId = member.id!! + ) + ) + } else { + throw SodaException("결제정보에 오류가 있습니다.") + } + } catch (e: Exception) { + throw SodaException("결제정보에 오류가 있습니다.") + } + } else { + throw SodaException("결제정보에 오류가 있습니다.") + } + } + @Transactional fun appleCharge(member: Member, request: AppleChargeRequest): ChargeResponse { val charge = Charge(request.chargeCan, 0) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/temp/ChargeTempService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/temp/ChargeTempService.kt index a578dac..8e2e645 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/temp/ChargeTempService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/temp/ChargeTempService.kt @@ -28,9 +28,9 @@ class ChargeTempService( private val objectMapper: ObjectMapper, - @Value("\${bootpay.application-id}") + @Value("\${bootpay.hecto-application-id}") private val bootpayApplicationId: String, - @Value("\${bootpay.private-key}") + @Value("\${bootpay.hecto-private-key}") private val bootpayPrivateKey: String ) { diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/calculate/CreatorAdminCalculateQueryRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/calculate/CreatorAdminCalculateQueryRepository.kt index 7f56747..590e27a 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/calculate/CreatorAdminCalculateQueryRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/calculate/CreatorAdminCalculateQueryRepository.kt @@ -176,12 +176,15 @@ class CreatorAdminCalculateQueryRepository(private val queryFactory: JPAQueryFac order.type, order.can, order.id.count(), - order.can.sum() + order.can.sum(), + creatorSettlementRatio.contentSettlementRatio ) ) .from(order) .innerJoin(order.audioContent, audioContent) .innerJoin(audioContent.member, member) + .leftJoin(creatorSettlementRatio) + .on(member.id.eq(creatorSettlementRatio.member.id)) .where( audioContent.member.id.eq(memberId) .and(order.isActive.isTrue) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/explorer/ExplorerService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/explorer/ExplorerService.kt index 20921fb..f6c620f 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/explorer/ExplorerService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/explorer/ExplorerService.kt @@ -301,11 +301,9 @@ class ExplorerService( member: Member, pageable: Pageable ): GetFollowerListResponse { - val totalCount = queryRepository - .getFollowerListTotalCount(creatorId) + val totalCount = queryRepository.getFollowerListTotalCount(creatorId) val followerList = queryRepository.getFollowerList(creatorId, pageable.offset, pageable.pageSize.toLong()) - .asSequence() .map { val isFollow = if (it.role == MemberRole.CREATOR) { queryRepository.isFollow(creatorId = it.userId, memberId = member.id!!) @@ -320,7 +318,6 @@ class ExplorerService( isFollow = isFollow ) } - .toList() return GetFollowerListResponse(totalCount = totalCount, items = followerList) } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 62f24c6..6dc7c92 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -11,6 +11,8 @@ logging: bootpay: applicationId: ${BOOTPAY_APPLICATION_ID} privateKey: ${BOOTPAY_PRIVATE_KEY} + hectoApplicationId: ${BOOTPAY_APPLICATION_HECTO_ID} + hectoPrivateKey: ${BOOTPAY_PRIVATE_HECTO_KEY} apple: iapVerifyUrl: https://buy.itunes.apple.com/verifyReceipt