-
Notifications
You must be signed in to change notification settings - Fork 17
/
IAMPortWebView.swift
191 lines (156 loc) · 6.94 KB
/
IAMPortWebView.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
//
// IAMPortWebView.swift
// SwiftyIamportDemo
//
// Created by Aaron Lee on 2020/12/08.
// Copyright © 2020 Aaron Lee. All rights reserved.
//
import SwiftUI
import UIKit
import SwiftyIamport
import WebKit
@available(iOS 13.0, *)
struct IAMPortWebView: UIViewControllerRepresentable {
@Binding var isPresented: Bool // 모달, 풀스크린 시트에 이용할 수 있습니다.
let paymentMethod: PaymentMethod // 커스텀 열거형을 선언하여 동적으로 활용할 수 있습니다.
/// 뷰 생성
func makeUIViewController(context: Context) -> some UIViewController {
let view = WKHtml5InicisViewControllerSwiftUI(isPresented: $isPresented, paymentMethod: paymentMethod)
return view
}
func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {}
}
@available(iOS 13.0, *)
class WKHtml5InicisViewControllerSwiftUI: UIViewController {
@Binding var isPresented: Bool
var paymentMethod: PaymentMethod
var pgType: IAMPortPGType // paymentMethod를 이용하여 PG사를 유동적으로 사용할 수 있습니다.
init(isPresented: Binding<Bool>, paymentMethod: PaymentMethod) {
self._isPresented = isPresented
self.paymentMethod = paymentMethod
switch paymentMethod {
case .credit:
self.pgType = .kcp
case .kakao:
self.pgType = .kakao
case .naver:
self.pgType = .naverpay
}
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
lazy var wkWebView: WKWebView = {
var view = WKWebView()
view.backgroundColor = UIColor.clear
view.navigationDelegate = self
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(wkWebView)
self.wkWebView.frame = self.view.frame
let safeAreaInsets = view.safeAreaInsets
wkWebView.translatesAutoresizingMaskIntoConstraints = false
wkWebView.topAnchor.constraint(equalTo: view.topAnchor, constant: safeAreaInsets.top).isActive = true
wkWebView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: safeAreaInsets.bottom).isActive = true
wkWebView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true
wkWebView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive = true
// 결제 환경 설정
IAMPortPay.sharedInstance.configure(scheme: "iamportPay", // info.plist에 설정한 scheme
storeIdentifier: "imp24420581") // iamport 에서 부여받은 가맹점 식별코드
IAMPortPay.sharedInstance
.setPGType(self.pgType) // PG사 타입
.setIdName(nil) // 상점아이디 ({PG사명}.{상점아이디}으로 생성시 사용)
.setPayMethod(.card) // 결제 형식
.setWKWebView(self.wkWebView) // 현재 Controller에 있는 WebView 지정
.setRedirectUrl("https://success.pay") // m_redirect_url 주소
// 결제 정보 데이타
let parameters: IAMPortParameters = [
"merchant_uid": String(format: "merchant_%@", String(Int(NSDate().timeIntervalSince1970 * 1000))),
"name": "결제테스트",
"amount": "1004",
"buyer_email": "demo@demo.inc",
"buyer_name": "테스트",
"buyer_tel": "010-3094-9303",
"buyer_addr": "서울특별시 강남구 역삼동",
"buyer_postcode": "01777",
"custom_data": ["A1": 123, "B1": "Hello"]
//"custom_data": "24"
]
IAMPortPay.sharedInstance.setParameters(parameters).commit()
// 결제 웹페이지(Local) 파일 호출
if let url = IAMPortPay.sharedInstance.urlFromLocalHtmlFile() {
let request = URLRequest(url: url)
self.wkWebView.load(request)
}
}
}
@available(iOS 13.0, *)
extension WKHtml5InicisViewControllerSwiftUI: WKNavigationDelegate {
/// 결제 결과 핸들러
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
let request = navigationAction.request
// 카카오 결제 승인 검사
if let urlString = request.url?.absoluteString {
if urlString.hasPrefix("https://service.iamport.kr/kakaopay_payments/kakaoApproval") {
print("APPROVED KAKAO PAY")
DispatchQueue.main.async {
self.isPresented.toggle()
}
}
}
// 그 외
IAMPortPay.sharedInstance.requestRedirectUrl(for: request, parser: { (data, response, error) -> Any? in
// Background Thread 처리
var resultData: [String: Any]?
if let httpResponse = response as? HTTPURLResponse {
let statusCode = httpResponse.statusCode
switch statusCode {
case 200:
resultData = [
"isSuccess": "OK"
]
break
default:
break
}
}
return resultData
}) { (pasingData) in
// Main Thread 처리
// 결제 완료 후
if let urlString = request.url?.absoluteString,
urlString.hasPrefix("https://success.pay") {
// 결제 승인 완료
self.isPresented.toggle()
}
}
let result = IAMPortPay.sharedInstance.requestAction(for: request)
decisionHandler(result ? .allow : .cancel)
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
// 결제 환경으로 설정에 의한 웹페이지(Local) 호출 결과
IAMPortPay.sharedInstance.requestIAMPortPayWKWebViewDidFinishLoad(webView) { (error) in
if error != nil {
switch error! {
case .custom(let reason):
print("error: \(reason)")
break
}
} else {
print("OK")
}
}
}
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
print("didFail")
}
func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
print("didFailProvisionalNavigation \(error.localizedDescription)")
}
}
enum PaymentMethod: String, CaseIterable {
case credit, kakao, naver
}