-
Notifications
You must be signed in to change notification settings - Fork 0
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
feature: 결제 승인 api #110
The head ref may contain hidden characters: "105-feature-\uACB0\uC81C-\uC2B9\uC778-api"
feature: 결제 승인 api #110
Changes from all commits
81bffa4
590cb51
9cd02d8
a70daf1
fc1f350
7f711a9
ad9c888
d633576
a6111dc
295d6e2
65f5734
e316163
dbe491d
7253ed1
4bb8b7b
e6492e9
49f246f
10dce1c
90c0a37
9094d1e
e7d7a59
9059ddb
d8c0f17
b119917
67eef66
6436c48
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
package com.petqua.application.payment | ||
|
||
import com.petqua.domain.order.OrderNumber | ||
import com.petqua.domain.payment.tosspayment.TossPaymentType | ||
import com.petqua.exception.payment.FailPaymentCode | ||
import com.petqua.exception.payment.FailPaymentException | ||
import com.petqua.exception.payment.FailPaymentExceptionType.ORDER_NUMBER_MISSING_EXCEPTION | ||
import java.math.BigDecimal | ||
|
||
data class SucceedPaymentCommand( | ||
val memberId: Long, | ||
val paymentType: TossPaymentType, | ||
val orderNumber: OrderNumber, | ||
val paymentKey: String, | ||
val amount: BigDecimal, | ||
) { | ||
fun toPaymentConfirmRequest(): PaymentConfirmRequestToPG { | ||
return PaymentConfirmRequestToPG( | ||
orderNumber = orderNumber, | ||
paymentKey = paymentKey, | ||
amount = amount | ||
) | ||
} | ||
|
||
companion object { | ||
fun of( | ||
memberId: Long, | ||
paymentType: String, | ||
orderId: String, | ||
paymentKey: String, | ||
amount: BigDecimal, | ||
): SucceedPaymentCommand { | ||
return SucceedPaymentCommand( | ||
memberId = memberId, | ||
paymentType = TossPaymentType.from(paymentType), | ||
orderNumber = OrderNumber.from(orderId), | ||
paymentKey = paymentKey, | ||
amount = amount, | ||
) | ||
} | ||
} | ||
} | ||
|
||
data class FailPaymentCommand( | ||
val memberId: Long, | ||
val code: FailPaymentCode, | ||
val message: String, | ||
val orderNumber: String?, | ||
) { | ||
|
||
fun toOrderNumber(): OrderNumber { | ||
return orderNumber?.let { OrderNumber.from(it) } ?: throw FailPaymentException(ORDER_NUMBER_MISSING_EXCEPTION) | ||
} | ||
|
||
companion object { | ||
fun of( | ||
memberId: Long, | ||
code: String, | ||
message: String, | ||
orderId: String?, | ||
): FailPaymentCommand { | ||
return FailPaymentCommand( | ||
memberId = memberId, | ||
code = FailPaymentCode.from(code), | ||
message = message, | ||
orderNumber = orderId, | ||
) | ||
} | ||
} | ||
} | ||
|
||
data class FailPaymentResponse( | ||
val code: FailPaymentCode, | ||
val message: String, | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package com.petqua.application.payment | ||
|
||
import com.petqua.exception.payment.FailPaymentCode.PAY_PROCESS_ABORTED | ||
import com.petqua.exception.payment.FailPaymentCode.PAY_PROCESS_CANCELED | ||
import com.petqua.exception.payment.FailPaymentCode.REJECT_CARD_COMPANY | ||
import org.slf4j.LoggerFactory | ||
import org.springframework.stereotype.Service | ||
|
||
@Service | ||
class PaymentFacadeService( | ||
private val paymentService: PaymentService, | ||
private val paymentGatewayService: PaymentGatewayService, | ||
) { | ||
|
||
private val log = LoggerFactory.getLogger(PaymentFacadeService::class.java) | ||
|
||
fun succeedPayment(command: SucceedPaymentCommand) { | ||
paymentService.validateAmount(command) | ||
val paymentResponse = paymentGatewayService.confirmPayment(command.toPaymentConfirmRequest()) | ||
paymentService.processPayment(paymentResponse.toPayment()) | ||
} | ||
|
||
fun failPayment(command: FailPaymentCommand): FailPaymentResponse { | ||
logFailPayment(command) | ||
if (command.code != PAY_PROCESS_CANCELED) { | ||
paymentService.cancelOrder(command.memberId, command.toOrderNumber()) | ||
} | ||
return FailPaymentResponse(command.code, command.message) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. 자주 묻는 질문 부분은 본 적이 없었는데 덕분에 궁금증이 일부 해결됐어요!!!!! 말씀하신 안내는 프론트에서 메시지를 띄워주는 것으로 충분할 것 같습니다! 어차피 저희가 할 수 있는 게 없습니다 |
||
} | ||
|
||
private fun logFailPayment(command: FailPaymentCommand) { | ||
when (command.code) { | ||
PAY_PROCESS_ABORTED -> log.error("PG사 혹은 원천사에서 결제를 중단했습니다. message: ${command.message}, OrderNumber: ${command.orderNumber}, MemberId: ${command.memberId}") | ||
PAY_PROCESS_CANCELED -> log.warn("사용자가 결제를 중단했습니다. message: ${command.message}, OrderNumber: ${command.orderNumber}, MemberId: ${command.memberId}") | ||
REJECT_CARD_COMPANY -> log.warn("카드사에서 결제를 거절했습니다. message: ${command.message}, OrderNumber: ${command.orderNumber}, MemberId: ${command.memberId}") | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
package com.petqua.application.payment | ||
|
||
import com.petqua.domain.order.OrderName | ||
import com.petqua.domain.order.OrderNumber | ||
import com.petqua.domain.payment.tosspayment.TossPayment | ||
import com.petqua.domain.payment.tosspayment.TossPaymentMethod | ||
import com.petqua.domain.payment.tosspayment.TossPaymentStatus | ||
import com.petqua.domain.payment.tosspayment.TossPaymentType | ||
import java.math.BigDecimal | ||
|
||
data class PaymentConfirmRequestToPG( | ||
val orderNumber: OrderNumber, | ||
val paymentKey: String, | ||
val amount: BigDecimal, | ||
) | ||
|
||
data class PaymentResponseFromPG( | ||
val version: String, | ||
val paymentKey: String, | ||
val type: String, | ||
val orderId: String, | ||
val orderName: String, | ||
val mid: String, | ||
val currency: String, | ||
val method: String, | ||
val totalAmount: BigDecimal, | ||
val balanceAmount: BigDecimal, | ||
val status: String, | ||
val requestedAt: String, | ||
val approvedAt: String, | ||
val useEscrow: Boolean, | ||
val lastTransactionKey: String?, | ||
val suppliedAmount: BigDecimal, | ||
val vat: BigDecimal, | ||
val cultureExpense: Boolean, | ||
val taxFreeAmount: BigDecimal, | ||
val taxExemptionAmount: BigDecimal, | ||
val cancels: List<CancelResponseFromPG>?, | ||
val isPartialCancelable: Boolean, | ||
val card: CardResponseFromPG?, | ||
val virtualAccount: VirtualAccountResponseFromPG?, | ||
val secret: String?, | ||
val mobilePhone: MobilePhoneResponseFromPG?, | ||
val giftCertificate: GiftCertificateResponseFromPG?, | ||
val transfer: TransferResponseFromPG?, | ||
val receipt: ReceiptResponseFromPG?, | ||
val checkout: CheckoutResponseFromPG?, | ||
val easyPay: EasyPayResponseFromPG?, | ||
val country: String, | ||
val failure: FailureResponseFromPG?, | ||
val cashReceipt: CashReceiptResponseFromPG?, | ||
val cashReceipts: List<CashReceiptHistoryResponseFromPG>?, | ||
val discount: DiscountResponseFromPG?, | ||
) { | ||
fun toPayment(): TossPayment { | ||
return TossPayment( | ||
paymentKey = paymentKey, | ||
orderNumber = OrderNumber.from(orderId), | ||
orderName = OrderName(orderName), | ||
method = TossPaymentMethod.valueOf(method), | ||
totalAmount = totalAmount, | ||
status = TossPaymentStatus.valueOf(status), | ||
requestedAt = requestedAt, | ||
approvedAt = approvedAt, | ||
useEscrow = useEscrow, | ||
type = TossPaymentType.valueOf(type), | ||
) | ||
} | ||
} | ||
|
||
data class CancelResponseFromPG( | ||
val cancelAmount: BigDecimal, | ||
val cancelReason: String, | ||
val taxFreeAmount: BigDecimal, | ||
val taxExemptionAmount: BigDecimal, | ||
val refundableAmount: BigDecimal, | ||
val easyPayDiscountAmount: BigDecimal, | ||
val canceledAt: String, | ||
val transactionKey: String, | ||
val receiptKey: String?, | ||
) | ||
|
||
data class CardResponseFromPG( | ||
val amount: BigDecimal, | ||
val issuerCode: String, | ||
val acquirerCode: String?, | ||
val number: String, | ||
val installmentPlanMonths: Int, | ||
val approveNo: String, | ||
val useCardPoint: Boolean, | ||
val cardType: String, | ||
val ownerType: String, | ||
val acquireStatus: String, | ||
val isInterestFree: Boolean, | ||
val interestPayer: String?, | ||
) | ||
|
||
data class VirtualAccountResponseFromPG( | ||
val accountType: String, | ||
val accountNumber: String, | ||
val bankCode: String, | ||
val customerName: String, | ||
val dueDate: String, | ||
val refundStatus: String, | ||
val expired: Boolean, | ||
val settlementStatus: String, | ||
val refundReceiveAccount: RefundReceiveAccountResponseFromPG?, // 결제창 띄운 시점부터 30분 동안만 조회 가능 | ||
) | ||
|
||
data class RefundReceiveAccountResponseFromPG( | ||
val bankCode: String, | ||
val accountNumber: String, | ||
val holderName: String, | ||
) | ||
|
||
data class MobilePhoneResponseFromPG( | ||
val customerMobilePhone: String, | ||
val settlementStatus: String, | ||
val receiptUrl: String, | ||
) | ||
|
||
data class GiftCertificateResponseFromPG( | ||
val approveNo: String, | ||
val settlementStatus: String, | ||
) | ||
|
||
data class TransferResponseFromPG( | ||
val bankCode: String, | ||
val settlementStatus: String, | ||
) | ||
|
||
data class ReceiptResponseFromPG( | ||
val url: String, | ||
) | ||
|
||
data class CheckoutResponseFromPG( | ||
val url: String, | ||
) | ||
|
||
data class EasyPayResponseFromPG( | ||
val provider: String, | ||
val amount: BigDecimal, | ||
val discountAmount: BigDecimal, | ||
) | ||
|
||
data class FailureResponseFromPG( | ||
val code: String, | ||
val message: String, | ||
) | ||
|
||
data class CashReceiptResponseFromPG( | ||
val type: String, | ||
val receiptKey: String, | ||
val issueNumber: String, | ||
val receiptUrl: String, | ||
val amount: BigDecimal, | ||
val taxFreeAmount: BigDecimal, | ||
) | ||
|
||
data class CashReceiptHistoryResponseFromPG( | ||
val receiptKey: String, | ||
val orderId: String, | ||
val orderName: String, | ||
val type: String, | ||
val issueNumber: String, | ||
val receiptUrl: String, | ||
val businessNumber: String, | ||
val transactionType: String, | ||
val amount: BigDecimal, | ||
val taxFreeAmount: BigDecimal, | ||
val issueStatus: String, | ||
val failure: FailureResponseFromPG, | ||
val customerIdentityNumber: String, | ||
val requestedAt: String, | ||
) | ||
|
||
data class DiscountResponseFromPG( | ||
val amount: BigDecimal, | ||
) | ||
|
||
data class PaymentErrorResponseFromPG( | ||
val code: String, | ||
val message: String, | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package com.petqua.application.payment | ||
|
||
import com.petqua.application.payment.infra.PaymentGatewayClient | ||
import org.springframework.stereotype.Service | ||
|
||
@Service | ||
class PaymentGatewayService( | ||
private val paymentGatewayClient: PaymentGatewayClient, | ||
) { | ||
|
||
fun confirmPayment(request: PaymentConfirmRequestToPG): PaymentResponseFromPG { | ||
return paymentGatewayClient.confirmPayment(request) | ||
} | ||
} |
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.
OrderPayment
도 여기서 생성되는 게 맞을까요??OrderPayment
에 수정이 있을 것 같아서 아직 구현하지 않으신 걸까요?? 😀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.
놓쳤습니다! 추가할게요. 여기서 생성되는 게 맞습니다.