Skip to content

Commit 2192777

Browse files
committed
Merge branch 'feature/SP-59-Stöd-för-att-visa-betalmenyn' into 'feature/native-payments'
Resolve SP-59 "Feature/ stöd för att visa betalmenyn" See merge request swedbank-pay/swedbank-pay-example-app-ios!7
2 parents 276f753 + dc21eef commit 2192777

File tree

3 files changed

+139
-29
lines changed

3 files changed

+139
-29
lines changed

Example-app/ViewControllers/PaymentViewController.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ extension PaymentViewController: SwedbankPaySDKDelegate {
205205
performSegue(withIdentifier: "showResult", sender: self)
206206
}
207207

208-
func sdkProblemOccurred(problem: SwedbankPaySDK.NativePaymentProblem) {
208+
func sdkProblemOccurred(problem: SwedbankPaySDK.PaymentSessionProblem) {
209209
PaymentViewModel.shared.setResult(.unknown)
210210
performSegue(withIdentifier: "showResult", sender: self)
211211
}
@@ -215,7 +215,7 @@ extension PaymentViewController: SwedbankPaySDKDelegate {
215215
performSegue(withIdentifier: "backToStore", sender: self)
216216
}
217217

218-
func availableInstrumentsFetched(_ availableInstruments: [SwedbankPaySDK.AvailableInstrument]) {
218+
func paymentSessionFetched(availableInstruments: [SwedbankPaySDK.AvailableInstrument]) {
219219

220220
}
221221

Example-app/ViewModels/StandaloneUrlViewModel.swift

Lines changed: 70 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import Foundation
2+
import SwiftUI
23
import SwedbankPaySDK
4+
import UIKit
35

46
extension StandaloneUrlView {
5-
class StandaloneUrlViewModel: ObservableObject, SwedbankPaySDKDelegate, SwedbankPaySDKNativePaymentDelegate {
7+
class StandaloneUrlViewModel: ObservableObject, SwedbankPaySDKDelegate, SwedbankPaySDKPaymentSessionDelegate {
68
@Published var viewCheckoutUrl: String = ""
79
@Published var baseUrl: String
810
@Published var completeUrl: String
@@ -18,6 +20,9 @@ extension StandaloneUrlView {
1820
@Published var displayScannerSheet: Bool = false
1921
@Published var isLoadingNativePayment: Bool = false
2022

23+
@Published var displayPaymentSessionSwedbankPayController: Bool = false
24+
@Published var paymentSessionSwedbankPayController: SwedbankPaySDKController?
25+
2126
@Published var showingAlert = false
2227
@Published var errorTitle: String?
2328
@Published var errorMessage: String?
@@ -26,9 +31,12 @@ extension StandaloneUrlView {
2631
@Published var paymentResultIcon: String?
2732
@Published var paymentResultMessage: String?
2833

29-
@Published var nativePayment: SwedbankPaySDK.NativePayment?
30-
@Published var availableInstrument: [SwedbankPaySDK.AvailableInstrument]?
31-
34+
@Published var nativePayment: SwedbankPaySDK.SwedbankPayPaymentSession?
35+
@Published var availableInstruments: [SwedbankPaySDK.AvailableInstrument]?
36+
37+
@Published var show3DSecureViewController = false
38+
@Published var paymentSession3DSecureViewController: UIViewController?
39+
3240
init() {
3341
baseUrl = String(StorageHelper.shared.value(for: .baseUrl) ?? "")
3442
completeUrl = String(StorageHelper.shared.value(for: .completeUrl) ?? "")
@@ -86,14 +94,15 @@ extension StandaloneUrlView {
8694
paymentResultMessage = resultText
8795

8896
displaySwedbankPayController = false
97+
displayPaymentSessionSwedbankPayController = false
8998
isLoadingNativePayment = false
9099

91100
viewCheckoutUrl = ""
92101
sessionApiUrl = ""
93102
swishNumber = ""
94103

95104
nativePayment = nil
96-
availableInstrument = nil
105+
availableInstruments = nil
97106
}
98107

99108
private func showAlert(error: Error, retry: (()->Void)? = nil) {
@@ -114,11 +123,19 @@ extension StandaloneUrlView {
114123
func paymentComplete() {
115124
setPaymentResult(success: true, resultText: "stand_alone_url_payment_successful".localize)
116125
}
117-
126+
127+
func paymentCanceled() {
128+
setPaymentResult(success: false, resultText: "stand_alone_url_payment_cancelled".localize)
129+
}
130+
118131
func paymentFailed(error: Error) {
119132
setPaymentResult(success: false, resultText: error.localizedDescription)
120133
}
121-
134+
135+
func paymentSessionComplete() {
136+
setPaymentResult(success: true, resultText: "stand_alone_url_payment_successful".localize)
137+
}
138+
122139
func sessionProblemOccurred(problem: SwedbankPaySDK.ProblemDetails) {
123140
var errorMessages: [String] = []
124141

@@ -134,7 +151,7 @@ extension StandaloneUrlView {
134151
errorMessage: "\(errorMessages.joined(separator: ": "))\n\n\(problem.type)")
135152
}
136153

137-
func sdkProblemOccurred(problem: SwedbankPaySDK.NativePaymentProblem) {
154+
func sdkProblemOccurred(problem: SwedbankPaySDK.PaymentSessionProblem) {
138155
switch problem {
139156
case .clientAppLaunchFailed:
140157
showAlert(errorTitle: nil,
@@ -145,16 +162,58 @@ extension StandaloneUrlView {
145162
setPaymentResult(success: false, resultText: "stand_alone_url_payment_session_end_state_reached".localize)
146163
case .internalInconsistencyError:
147164
setPaymentResult(success: false, resultText: "stand_alone_internal_inconsistency_error".localize)
165+
case .automaticConfigurationFailed:
166+
setPaymentResult(success: false, resultText: "stand_alone_automatic_configuration_failed".localize)
148167
}
149168
}
150169

151-
func paymentCanceled() {
170+
func paymentSessionCanceled() {
152171
setPaymentResult(success: false, resultText: "stand_alone_url_payment_cancelled".localize)
153172
}
154173

155-
func availableInstrumentsFetched(_ availableInstruments: [SwedbankPaySDK.AvailableInstrument]) {
156-
self.availableInstrument = availableInstruments
174+
func paymentSessionFetched(availableInstruments: [SwedbankPaySDK.AvailableInstrument]) {
175+
self.availableInstruments = availableInstruments
157176
isLoadingNativePayment = false
158177
}
178+
179+
func show3DSecureViewController(viewController: UIViewController) {
180+
self.paymentSession3DSecureViewController = viewController
181+
self.show3DSecureViewController = true
182+
}
183+
184+
func dismiss3DSecureViewController() {
185+
self.show3DSecureViewController = false
186+
self.paymentSession3DSecureViewController = nil
187+
}
188+
189+
func paymentSession3DSecureViewControllerLoadFailed(error: Error, retry: @escaping ()->Void) {
190+
let alert = UIAlertController(title: nil,
191+
message: "\((error as NSError).code): \(error.localizedDescription)\n\n\((error as NSError).domain)",
192+
preferredStyle: .alert)
193+
alert.addAction(UIAlertAction(title: "general_ok".localize, style: .cancel, handler: { _ in
194+
self.show3DSecureViewController = false
195+
self.paymentSession3DSecureViewController = nil
196+
}))
197+
198+
alert.addAction(UIAlertAction(title: "general_retry".localize, style: .default, handler: { _ in
199+
retry()
200+
}))
201+
202+
self.paymentSession3DSecureViewController?.present(alert, animated: true, completion: nil)
203+
}
204+
}
205+
}
206+
207+
struct SomeView: UIViewControllerRepresentable {
208+
var viewController: UIViewController
209+
210+
typealias UIViewControllerType = UIViewController
211+
212+
func makeUIViewController(context: Context) -> UIViewController {
213+
return viewController
214+
}
215+
216+
func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
217+
//update Content
159218
}
160219
}

Example-app/Views/StandaloneUrlView.swift

Lines changed: 67 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -269,13 +269,12 @@ struct StandaloneUrlView: View {
269269
Button {
270270
isFocused = false
271271

272-
if let configuration = viewModel.configurePayment(),
273-
let sessionURL = URL(string: viewModel.sessionApiUrl) {
274-
viewModel.nativePayment = SwedbankPaySDK.NativePayment(orderInfo: configuration.orderInfo)
272+
if let sessionURL = URL(string: viewModel.sessionApiUrl) {
273+
viewModel.nativePayment = SwedbankPaySDK.SwedbankPayPaymentSession()
275274
viewModel.nativePayment?.delegate = viewModel
276275

277-
viewModel.nativePayment?.startPaymentSession(sessionURL: sessionURL)
278276
viewModel.isLoadingNativePayment = true
277+
viewModel.nativePayment?.fetchPaymentSession(sessionURL: sessionURL)
279278
viewModel.paymentResultIcon = nil
280279
viewModel.paymentResultMessage = nil
281280
}
@@ -292,8 +291,8 @@ struct StandaloneUrlView: View {
292291
.cornerRadius(30)
293292
.padding(.top, 10)
294293

295-
if let availableInstrument = viewModel.availableInstrument {
296-
ForEach(availableInstrument, id: \.self) { instrument in
294+
if let availableInstruments = viewModel.availableInstruments {
295+
ForEach(availableInstruments, id: \.self) { instrument in
297296
switch instrument {
298297
case .swish(let prefills):
299298
VStack(spacing: 4) {
@@ -327,9 +326,9 @@ struct StandaloneUrlView: View {
327326

328327
Button {
329328
isFocused = false
330-
331-
viewModel.nativePayment?.makePaymentAttempt(instrument: .swish(msisdn: viewModel.swishNumber))
329+
332330
viewModel.isLoadingNativePayment = true
331+
viewModel.nativePayment?.makeNativePaymentAttempt(instrument: .swish(msisdn: viewModel.swishNumber))
333332
} label: {
334333
Text("stand_alone_url_payment_swish")
335334
.smallFont()
@@ -346,8 +345,8 @@ struct StandaloneUrlView: View {
346345
Button {
347346
isFocused = false
348347

349-
viewModel.nativePayment?.makePaymentAttempt(instrument: .swish(msisdn: nil))
350348
viewModel.isLoadingNativePayment = true
349+
viewModel.nativePayment?.makeNativePaymentAttempt(instrument: .swish(msisdn: nil))
351350
} label: {
352351
Text("stand_alone_url_payment_swish_device")
353352
.smallFont()
@@ -365,8 +364,8 @@ struct StandaloneUrlView: View {
365364
Button {
366365
isFocused = false
367366

368-
viewModel.nativePayment?.makePaymentAttempt(instrument: .swish(msisdn: prefill.msisdn))
369367
viewModel.isLoadingNativePayment = true
368+
viewModel.nativePayment?.makeNativePaymentAttempt(instrument: .swish(msisdn: prefill.msisdn))
370369
} label: {
371370
Text("stand_alone_url_payment_swish_prefill \(prefill.msisdn)")
372371
.smallFont()
@@ -380,16 +379,62 @@ struct StandaloneUrlView: View {
380379
.padding(.top, 10)
381380
}
382381
}
382+
case .creditCard(prefills: let prefills):
383+
if let prefills = prefills {
384+
ForEach(prefills, id: \.rank) { prefill in
385+
Button {
386+
isFocused = false
387+
388+
viewModel.isLoadingNativePayment = true
389+
viewModel.nativePayment?.makeNativePaymentAttempt(instrument: .creditCard(prefill: prefill))
390+
} label: {
391+
VStack(spacing: 0) {
392+
Text("stand_alone_url_payment_credit_card_prefill \(prefill.cardBrand)")
393+
Text("\(prefill.maskedPan) \(prefill.expiryString)")
394+
}
395+
.smallFont()
396+
.frame(maxWidth: .infinity)
397+
.frame(height: 48)
398+
.accessibilityIdentifier("creditCardPrefillButton")
399+
400+
}
401+
.foregroundColor(.white)
402+
.background(.black)
403+
.cornerRadius(30)
404+
.padding(.top, 10)
405+
}
406+
}
407+
case .webBased(identifier: let identifier):
408+
EmptyView()
383409
}
384410
}
411+
412+
Button {
413+
isFocused = false
414+
415+
viewModel.paymentSessionSwedbankPayController = viewModel.nativePayment?.createSwedbankPaySDKController()
416+
viewModel.paymentSessionSwedbankPayController?.delegate = viewModel
417+
viewModel.displayPaymentSessionSwedbankPayController = true
418+
} label: {
419+
Text("Get payment menu")
420+
.smallFont()
421+
.frame(maxWidth: .infinity)
422+
.frame(height: 48)
423+
.accessibilityIdentifier("webBasedButton")
424+
425+
}
426+
.foregroundColor(.white)
427+
.background(.black)
428+
.cornerRadius(30)
429+
.padding(.top, 10)
385430
}
386431

387432
if viewModel.nativePayment != nil {
388433
Button {
389434
isFocused = false
390435

391-
viewModel.nativePayment?.abortPaymentSession()
392436
viewModel.isLoadingNativePayment = true
437+
viewModel.nativePayment?.abortPaymentSession()
393438
} label: {
394439
Text("stand_alone_url_payment_abort")
395440
.smallFont()
@@ -415,8 +460,8 @@ struct StandaloneUrlView: View {
415460
reader.scrollTo(0, anchor: .top)
416461
}
417462
}
418-
.onChange(of: viewModel.availableInstrument) { _ in
419-
guard viewModel.availableInstrument != nil else {
463+
.onChange(of: viewModel.availableInstruments) { _ in
464+
guard viewModel.availableInstruments != nil else {
420465
return
421466
}
422467

@@ -429,18 +474,24 @@ struct StandaloneUrlView: View {
429474
SwedbankPayView(swedbankPayConfiguration: configuration, delegate: viewModel, nativePaymentDelegate: viewModel)
430475
}
431476
}
477+
.sheet(isPresented: $viewModel.displayPaymentSessionSwedbankPayController) {
478+
SomeView(viewController: viewModel.paymentSessionSwedbankPayController!)
479+
}
432480
.sheet(isPresented: $viewModel.displayScannerSheet) {
433481
self.scannerSheet
434482
}
483+
.sheet(isPresented: $viewModel.show3DSecureViewController) {
484+
SomeView(viewController: viewModel.paymentSession3DSecureViewController!)
485+
}
435486
.alert(viewModel.errorTitle ?? "stand_alone_generic_error_title".localize,
436487
isPresented: $viewModel.showingAlert,
437488
actions: {
438489
Button("general_ok".localize, role: .cancel) { }
439490

440491
if let retry = viewModel.retry {
441492
Button("general_retry".localize) {
442-
retry()
443493
viewModel.isLoadingNativePayment = true
494+
retry()
444495
}
445496
}
446497
},
@@ -486,9 +537,9 @@ struct SwedbankPayView: UIViewControllerRepresentable {
486537

487538
private let swedbankPayConfiguration: SwedbankPayConfiguration
488539
private let delegate: SwedbankPaySDKDelegate
489-
private let nativePaymentDelegate: SwedbankPaySDKNativePaymentDelegate
540+
private let nativePaymentDelegate: SwedbankPaySDKPaymentSessionDelegate
490541

491-
init(swedbankPayConfiguration: SwedbankPayConfiguration, delegate: SwedbankPaySDKDelegate, nativePaymentDelegate: SwedbankPaySDKNativePaymentDelegate) {
542+
init(swedbankPayConfiguration: SwedbankPayConfiguration, delegate: SwedbankPaySDKDelegate, nativePaymentDelegate: SwedbankPaySDKPaymentSessionDelegate) {
492543
self.swedbankPayConfiguration = swedbankPayConfiguration
493544
self.delegate = delegate
494545
self.nativePaymentDelegate = nativePaymentDelegate

0 commit comments

Comments
 (0)