feat(can-charge): 이롬넷(Payverse) 통합결제 추가

This commit is contained in:
Yu Sung
2025-10-01 01:48:18 +09:00
parent e62c89d7bc
commit d045722b8d
13 changed files with 639 additions and 72 deletions

View File

@@ -11,12 +11,14 @@ import BootpayUI
struct CanPgPaymentView: View {
@StateObject var viewModel = CanPgPaymentViewModel()
@EnvironmentObject var viewModel: CanPgPaymentViewModel
let canResponse: GetCanResponse
let refresh: () -> Void
let afterCompletionToGoBack: Bool
@State private var showExitConfirm: Bool = false
init(canResponse: GetCanResponse, refresh: @escaping () -> Void, afterCompletionToGoBack: Bool) {
self.canResponse = canResponse
self.refresh = refresh
@@ -64,6 +66,37 @@ struct CanPgPaymentView: View {
DEBUG_LOG("onClose")
viewModel.isShowPaymentView = false
}
} else if viewModel.isShowPayversePaymentView {
ZStack(alignment: .topLeading) {
PayverseWebView(startPayloadJson: viewModel.payversePayloadJson)
.ignoresSafeArea(edges: .bottom)
HStack(spacing: 8) {
Button(action: { showExitConfirm = true }) {
Text("닫기")
.font(.custom(Font.bold.rawValue, size: 14))
.foregroundColor(.white)
.padding(.horizontal, 12)
.padding(.vertical, 8)
.background(Color.black.opacity(0.6))
.clipShape(Capsule())
}
.padding(.leading, 16)
.padding(.top, 12)
Spacer()
}
}
.background(Color.black.ignoresSafeArea())
.alert("결제를 종료할까요?", isPresented: $showExitConfirm) {
Button("계속", role: .cancel) { }
Button("종료", role: .destructive) {
DEBUG_LOG("Payverse: user requested to exit")
viewModel.isShowPayversePaymentView = false
//
AppState.shared.back()
}
} message: {
Text("진행 중인 결제를 중단하고 이전 화면으로 돌아갑니다.")
}
} else {
GeometryReader { proxy in
VStack(spacing: 0) {
@@ -102,15 +135,14 @@ struct CanPgPaymentView: View {
.frame(width: screenSize().width - 26.7, alignment: .leading)
.padding(.top, 26.7)
HStack(spacing: 13.3) {
Text("카드")
.font(.custom( viewModel.paymentMethod == .card ? Font.bold.rawValue : Font.medium.rawValue, size: 16.7))
.foregroundColor(viewModel.paymentMethod == .card ? Color.button : Color.grayee)
HStack(spacing: 16.7) {
Text("통합 결제")
.font(.custom( viewModel.paymentMethod == .unified ? Font.bold.rawValue : Font.medium.rawValue, size: 16.7))
.foregroundColor(viewModel.paymentMethod == .unified ? Color.button : Color.grayee)
.frame(maxWidth: .infinity)
.padding(.vertical, 16.7)
.background(
viewModel.paymentMethod == .card ?
viewModel.paymentMethod == .unified ?
Color.button.opacity(0.3) :
Color.gray23
)
@@ -118,60 +150,11 @@ struct CanPgPaymentView: View {
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(lineWidth: 1)
.foregroundColor(viewModel.paymentMethod == .card ? Color.button : Color.gray77)
.foregroundColor(viewModel.paymentMethod == .unified ? Color.button : Color.gray77)
)
.onTapGesture {
if viewModel.paymentMethod != .card {
viewModel.paymentMethod = .card
}
}
Text("계좌이체")
.font(.custom( viewModel.paymentMethod == .bank ? Font.bold.rawValue : Font.medium.rawValue, size: 16.7))
.foregroundColor(viewModel.paymentMethod == .bank ? Color.button : Color.grayee)
.frame(maxWidth: .infinity)
.padding(.vertical, 16.7)
.background(
viewModel.paymentMethod == .bank ?
Color.button.opacity(0.3) :
Color.gray23
)
.cornerRadius(10)
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(lineWidth: 1)
.foregroundColor(viewModel.paymentMethod == .bank ? Color.button : Color.gray77)
)
.onTapGesture {
if viewModel.paymentMethod != .bank {
viewModel.paymentMethod = .bank
}
}
}
.frame(width: screenSize().width - 26.7)
.padding(.top, 16.7)
HStack(spacing: 13.3) {
Text("휴대폰 결제")
.font(.custom( viewModel.paymentMethod == .phone ? Font.bold.rawValue : Font.medium.rawValue, size: 16.7))
.foregroundColor(viewModel.paymentMethod == .phone ? Color.button : Color.grayee)
.frame(maxWidth: .infinity)
.padding(.vertical, 16.7)
.background(
viewModel.paymentMethod == .phone ?
Color.button.opacity(0.3) :
Color.gray23
)
.cornerRadius(10)
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(lineWidth: 1)
.foregroundColor(viewModel.paymentMethod == .phone ? Color.button : Color.gray77)
)
.onTapGesture {
if viewModel.paymentMethod != .phone {
viewModel.paymentMethod = .phone
if viewModel.paymentMethod != .unified {
viewModel.paymentMethod = .unified
}
}
@@ -195,6 +178,28 @@ struct CanPgPaymentView: View {
viewModel.paymentMethod = .kakaopay
}
}
Text("휴대폰 결제")
.font(.custom( viewModel.paymentMethod == .phone ? Font.bold.rawValue : Font.medium.rawValue, size: 16.7))
.foregroundColor(viewModel.paymentMethod == .phone ? Color.button : Color.grayee)
.frame(maxWidth: .infinity)
.padding(.vertical, 16.7)
.background(
viewModel.paymentMethod == .phone ?
Color.button.opacity(0.3) :
Color.gray23
)
.cornerRadius(10)
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(lineWidth: 1)
.foregroundColor(viewModel.paymentMethod == .phone ? Color.button : Color.gray77)
)
.onTapGesture {
if viewModel.paymentMethod != .phone {
viewModel.paymentMethod = .phone
}
}
}
.frame(width: screenSize().width - 26.7)
.padding(.top, 16.7)
@@ -299,12 +304,16 @@ struct CanPgPaymentView: View {
viewModel.errorMessage = "결제진행에 동의하셔야 결제가 가능합니다."
viewModel.isShowPopup = true
} else {
viewModel.chargeCan(canId: canResponse.id) {
viewModel.payload.orderName = canResponse.title
viewModel.payload.price = Double(canResponse.price)
viewModel.payload.taxFree = 0
viewModel.isShowPaymentView = true
if viewModel.paymentMethod == .unified {
viewModel.payverseChargeCan(canId: canResponse.id)
} else {
viewModel.chargeCan(canId: canResponse.id) {
viewModel.payload.orderName = canResponse.title
viewModel.payload.price = Double(canResponse.price)
viewModel.payload.taxFree = 0
viewModel.isShowPaymentView = true
}
}
}
}
@@ -348,6 +357,21 @@ struct CanPgPaymentView: View {
LoadingView()
}
}
.onAppear {
viewModel.canResponse = canResponse
viewModel.refresh = refresh
viewModel.afterCompletionToGoBack = afterCompletionToGoBack
}
.onDisappear {
viewModel.canResponse = nil
viewModel.refresh = nil
viewModel.afterCompletionToGoBack = nil
viewModel.paymentMethod = nil
viewModel.isTermsAgree = false
viewModel.isShowPaymentView = false
viewModel.isShowPayversePaymentView = false
}
}
}