From 3ae9792f3f11ca65f2f2c012069ef8c026e15f9b Mon Sep 17 00:00:00 2001 From: Alan Maynard Date: Fri, 29 Mar 2019 18:38:20 -0400 Subject: [PATCH 01/13] SWE-12 New class to handle payment result - also changed target for `PaymentDetailInterfaceController` --- .../PaymentResultInterfaceController.swift | 31 +++++++++++++++++++ .../project.pbxproj | 6 ++-- 2 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentResultInterfaceController.swift diff --git a/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentResultInterfaceController.swift b/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentResultInterfaceController.swift new file mode 100644 index 0000000..b517cd6 --- /dev/null +++ b/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentResultInterfaceController.swift @@ -0,0 +1,31 @@ +// +// PaymentResultInterfaceController.swift +// SynchronyFinancial WatchKit Extension +// +// Created by Alan Maynard on 3/29/19. +// Copyright © 2019 Alan Maynard. All rights reserved. +// + +import WatchKit +import Foundation + + +class PaymentResultInterfaceController: WKInterfaceController { + + override func awake(withContext context: Any?) { + super.awake(withContext: context) + + // Configure interface objects here. + } + + override func willActivate() { + // This method is called when watch view controller is about to be visible to user + super.willActivate() + } + + override func didDeactivate() { + // This method is called when watch view controller is no longer visible + super.didDeactivate() + } + +} diff --git a/SynchronyFinancial/SynchronyFinancial.xcodeproj/project.pbxproj b/SynchronyFinancial/SynchronyFinancial.xcodeproj/project.pbxproj index 6d5600b..8aa6464 100644 --- a/SynchronyFinancial/SynchronyFinancial.xcodeproj/project.pbxproj +++ b/SynchronyFinancial/SynchronyFinancial.xcodeproj/project.pbxproj @@ -9,7 +9,6 @@ /* Begin PBXBuildFile section */ 1123372E223ABD6400B70925 /* FetchData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1123372D223ABD6400B70925 /* FetchData.swift */; }; 281283568A34D3C5D9C7B383 /* libPods-SynchronyFinancial WatchKit Extension.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CAA6D46F907ADAABF49FD409 /* libPods-SynchronyFinancial WatchKit Extension.a */; }; - 481864A8224802BB0059CF7A /* PaymentDetailInterfaceController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 481864A7224802BB0059CF7A /* PaymentDetailInterfaceController.swift */; }; 481864A9224802BB0059CF7A /* PaymentDetailInterfaceController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 481864A7224802BB0059CF7A /* PaymentDetailInterfaceController.swift */; }; 48DA0058221D12E70081A500 /* AccountCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 48DA0057221D12E70081A500 /* AccountCell.swift */; }; 48F243072214C98600B9C894 /* AccountTableInterfaceController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 48F243062214C98600B9C894 /* AccountTableInterfaceController.swift */; }; @@ -27,6 +26,7 @@ 678C38842230950100FEAAF6 /* AccountDetailsInterfaceController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 678C38832230950100FEAAF6 /* AccountDetailsInterfaceController.swift */; }; 678C3885223098C400FEAAF6 /* Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = 48F2430B2214CBF700B9C894 /* Account.swift */; }; 678C388622309F7D00FEAAF6 /* AccountCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 48DA0057221D12E70081A500 /* AccountCell.swift */; }; + 678C62BA224ECDFD0007AD53 /* PaymentResultInterfaceController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 678C62B9224ECDFD0007AD53 /* PaymentResultInterfaceController.swift */; }; 67BAC269219E254700713FEF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67BAC268219E254700713FEF /* AppDelegate.swift */; }; 67BAC26E219E254700713FEF /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 67BAC26C219E254700713FEF /* Main.storyboard */; }; 67BAC270219E254800713FEF /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 67BAC26F219E254800713FEF /* Assets.xcassets */; }; @@ -101,6 +101,7 @@ 676392B322429DC800740A8C /* TransactionsInterfaceController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionsInterfaceController.swift; sourceTree = ""; }; 676392B52242A3F800740A8C /* TransactionCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionCell.swift; sourceTree = ""; }; 678C38832230950100FEAAF6 /* AccountDetailsInterfaceController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountDetailsInterfaceController.swift; sourceTree = ""; }; + 678C62B9224ECDFD0007AD53 /* PaymentResultInterfaceController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaymentResultInterfaceController.swift; sourceTree = ""; }; 67BAC265219E254700713FEF /* SynchronyFinancial.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SynchronyFinancial.app; sourceTree = BUILT_PRODUCTS_DIR; }; 67BAC268219E254700713FEF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 67BAC26D219E254700713FEF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; @@ -200,6 +201,7 @@ 67BAC28A219E254900713FEF /* SynchronyFinancial WatchKit Extension */ = { isa = PBXGroup; children = ( + 678C62B9224ECDFD0007AD53 /* PaymentResultInterfaceController.swift */, 674BD1522239A39D0076AFD6 /* PayBillInterfaceController.swift */, 481864A7224802BB0059CF7A /* PaymentDetailInterfaceController.swift */, 676392B322429DC800740A8C /* TransactionsInterfaceController.swift */, @@ -467,7 +469,6 @@ 674BD1532239A39D0076AFD6 /* PayBillInterfaceController.swift in Sources */, 48F2430D2214CBF700B9C894 /* Account.swift in Sources */, 678C388622309F7D00FEAAF6 /* AccountCell.swift in Sources */, - 481864A8224802BB0059CF7A /* PaymentDetailInterfaceController.swift in Sources */, 48F2430E2214CBF700B9C894 /* Transaction.swift in Sources */, 67BAC269219E254700713FEF /* AppDelegate.swift in Sources */, ); @@ -480,6 +481,7 @@ 678C3885223098C400FEAAF6 /* Account.swift in Sources */, 67BAC28E219E254900713FEF /* ExtensionDelegate.swift in Sources */, 674BD1542239A39D0076AFD6 /* PayBillInterfaceController.swift in Sources */, + 678C62BA224ECDFD0007AD53 /* PaymentResultInterfaceController.swift in Sources */, 678C38842230950100FEAAF6 /* AccountDetailsInterfaceController.swift in Sources */, 673F396E21A644570051469E /* MainMenuInterfaceController.swift in Sources */, 67E17B87223812C2008871FE /* Defaults.swift in Sources */, From 2e991f602dab1ecd45a4c7441437a3a4ed98cdc7 Mon Sep 17 00:00:00 2001 From: Alan Maynard Date: Fri, 29 Mar 2019 18:40:27 -0400 Subject: [PATCH 02/13] SWE-12 Static member to handle date formatting --- SynchronyFinancial/SynchronyFinancial/Defaults.swift | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/SynchronyFinancial/SynchronyFinancial/Defaults.swift b/SynchronyFinancial/SynchronyFinancial/Defaults.swift index 375d8a3..6da079f 100644 --- a/SynchronyFinancial/SynchronyFinancial/Defaults.swift +++ b/SynchronyFinancial/SynchronyFinancial/Defaults.swift @@ -22,6 +22,13 @@ final class Defaults { static let token = UserDefaults.standard.string(forKey: "access_token") ?? "" static let authHeader = ["Authorization": "Bearer \(token)"] + static let careCreditDateFormatter: DateFormatter = { + var formatter = DateFormatter() + formatter.dateFormat = "yyyyMMdd" + formatter.locale = Locale.current + return formatter + }() + static var headerForLogin: [String: Any] = { return ["client_id": "carecredit", "client_secret": "", @@ -55,7 +62,6 @@ final class Defaults { let start_date = formatter.string(from: Calendar.current.date(byAdding: .day, value: -14, to: Date()) ?? Date()) let end_date = formatter.string(from: Date()) - return ["account_alias": account_alias, "begin_sequence": "1", "end_date": end_date, From a2689bdd39e083f2201cdd7b170607abe5e1f430 Mon Sep 17 00:00:00 2001 From: Alan Maynard Date: Fri, 29 Mar 2019 18:40:52 -0400 Subject: [PATCH 03/13] SWE-12 Define web service call for making payment --- .../FetchData.swift | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/SynchronyFinancial/SynchronyFinancial WatchKit Extension/FetchData.swift b/SynchronyFinancial/SynchronyFinancial WatchKit Extension/FetchData.swift index a45a644..1fc71f1 100644 --- a/SynchronyFinancial/SynchronyFinancial WatchKit Extension/FetchData.swift +++ b/SynchronyFinancial/SynchronyFinancial WatchKit Extension/FetchData.swift @@ -20,7 +20,7 @@ class FetchData { completion(false, NSError()) return } - + if let token = dict["access_token"]?.string { // now we should save our token somewhere safe (UserDefaults) UserDefaults.standard.set(token, forKey: "access_token") @@ -107,4 +107,28 @@ class FetchData { } } } + + static func submitPayment(for alias: String, type: String, amount: Double, bankID: String, completion: @escaping (String, String, Error?) -> Void) { + var paymentHeader = Defaults.headerForPmt + paymentHeader["account_alias"] = alias + paymentHeader["bank_account_id"] = bankID + paymentHeader["payment_amount_type"] = type + paymentHeader["payment_amount"] = amount + paymentHeader["scheduled_payment_post_date"] = Defaults.careCreditDateFormatter.string(from: Date()) + + + Alamofire.request(Defaults.MAKE_PAYMENT_URL, method: .post, parameters: paymentHeader, encoding: JSONEncoding.default, headers: Defaults.authHeader).responseJSON { payload in + switch payload.result { + case .success(let value): + let dict = JSON(value).dictionaryValue + guard dict["status"]?.dictionaryValue["response_code"]?.string == "0" else { return } + if let paymentConfirmationNum = dict["payment_confirmation_number"]?.stringValue, + let paymentID = dict["payment_id"]?.stringValue { + completion(paymentConfirmationNum, paymentID, nil) + } + case .failure(let error): + NSLog("Error: \(error.localizedDescription)") + } + } + } } From 511f4f578e7dcb7d4afc6571b31b0935652dedc1 Mon Sep 17 00:00:00 2001 From: Alan Maynard Date: Fri, 29 Mar 2019 18:42:06 -0400 Subject: [PATCH 04/13] SWE-12 handle web service call and prepare to push to payment result --- .../PaymentDetailInterfaceController.swift | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentDetailInterfaceController.swift b/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentDetailInterfaceController.swift index 30ed7b8..2be4347 100644 --- a/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentDetailInterfaceController.swift +++ b/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentDetailInterfaceController.swift @@ -12,6 +12,7 @@ import Foundation class PaymentDetailInterfaceController: WKInterfaceController { var selectedAccount: Account? var dictForAcct: [String: Account] = [:] + var dictForPayment: [String: String] = [:] var paymentButtonArmed: Bool = false var paymentAmount: Double = 0.0 @@ -34,6 +35,14 @@ class PaymentDetailInterfaceController: WKInterfaceController { @IBAction func paymentAction() { if paymentButtonArmed { popToRootController() + guard let alias = selectedAccount?.accountAlias else { return } + FetchData.submitPayment(for: alias, type: "CBL", amount: 20.00, bankID: "9999") { confirmationNum, paymentID, error in + guard error == nil else { return } + self.dictForPayment.updateValue(confirmationNum, forKey: "payment_confirmation_number") + self.dictForPayment.updateValue(paymentID, forKey: "payment_id") + } + +// popToRootController() } else { // animate(withDuration: 0.75) { // self.paymentButton.setBackgroundColor(UIColor.init(red: 141, green: 241, blue: 48, alpha: 1.0)) From 6f9d87c236fa3bdfa915d4749dd2e42a6b10893f Mon Sep 17 00:00:00 2001 From: Alan Maynard Date: Fri, 29 Mar 2019 18:43:10 -0400 Subject: [PATCH 05/13] SWE-12 Set up Payment Result view - we now will receive a dictionary in Payment Result which contains (for now) the payment confirmation number and payment id - these are displayed in the labels --- .../Base.lproj/Interface.storyboard | 25 +++++++++++++++++++ .../PaymentDetailInterfaceController.swift | 2 +- .../PaymentResultInterfaceController.swift | 16 +++++++++--- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/SynchronyFinancial/SynchronyFinancial WatchKit App/Base.lproj/Interface.storyboard b/SynchronyFinancial/SynchronyFinancial WatchKit App/Base.lproj/Interface.storyboard index ed397d2..4ccc998 100644 --- a/SynchronyFinancial/SynchronyFinancial WatchKit App/Base.lproj/Interface.storyboard +++ b/SynchronyFinancial/SynchronyFinancial WatchKit App/Base.lproj/Interface.storyboard @@ -224,6 +224,31 @@ + + + + + + + + + + + + + + diff --git a/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentDetailInterfaceController.swift b/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentDetailInterfaceController.swift index 2be4347..8992f0c 100644 --- a/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentDetailInterfaceController.swift +++ b/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentDetailInterfaceController.swift @@ -34,12 +34,12 @@ class PaymentDetailInterfaceController: WKInterfaceController { @IBAction func paymentAction() { if paymentButtonArmed { - popToRootController() guard let alias = selectedAccount?.accountAlias else { return } FetchData.submitPayment(for: alias, type: "CBL", amount: 20.00, bankID: "9999") { confirmationNum, paymentID, error in guard error == nil else { return } self.dictForPayment.updateValue(confirmationNum, forKey: "payment_confirmation_number") self.dictForPayment.updateValue(paymentID, forKey: "payment_id") + self.pushController(withName: "PaymentResult", context: self.dictForPayment) } // popToRootController() diff --git a/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentResultInterfaceController.swift b/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentResultInterfaceController.swift index b517cd6..6bf3c42 100644 --- a/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentResultInterfaceController.swift +++ b/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentResultInterfaceController.swift @@ -9,13 +9,23 @@ import WatchKit import Foundation - class PaymentResultInterfaceController: WKInterfaceController { + @IBOutlet var confirmationNumberLabel: WKInterfaceLabel! + @IBOutlet var paymentIDLabel: WKInterfaceLabel! override func awake(withContext context: Any?) { super.awake(withContext: context) - - // Configure interface objects here. + + if let data = context as? [String: String], + let paymentConfirmation = data["payment_confirmation_number"], + let paymentID = data["payment_id"] { + confirmationNumberLabel.setText(paymentConfirmation) + paymentIDLabel.setText(paymentID) + } + } + + @IBAction func didTapHome() { + popToRootController() } override func willActivate() { From 0e76bccb4be1253e5fae95abacd3316093deef7d Mon Sep 17 00:00:00 2001 From: Alan Maynard Date: Fri, 29 Mar 2019 18:57:36 -0400 Subject: [PATCH 06/13] SWE-12 Navigation changes - in order to avoid having a back button on the Payment Result screen, we present it modally and then pop to the root controller - this gives the user a view with Cancel in the left corner, and a Home button. Tapping cancel will dismiss the modal, showing the Home screen --- .../PaymentDetailInterfaceController.swift | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentDetailInterfaceController.swift b/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentDetailInterfaceController.swift index 8992f0c..32df8da 100644 --- a/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentDetailInterfaceController.swift +++ b/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentDetailInterfaceController.swift @@ -39,10 +39,9 @@ class PaymentDetailInterfaceController: WKInterfaceController { guard error == nil else { return } self.dictForPayment.updateValue(confirmationNum, forKey: "payment_confirmation_number") self.dictForPayment.updateValue(paymentID, forKey: "payment_id") - self.pushController(withName: "PaymentResult", context: self.dictForPayment) + self.presentController(withName: "PaymentResult", context: self.dictForPayment) + self.popToRootController() } - -// popToRootController() } else { // animate(withDuration: 0.75) { // self.paymentButton.setBackgroundColor(UIColor.init(red: 141, green: 241, blue: 48, alpha: 1.0)) From 1b1aadd070e7538f19bbcc4dd1901fbcba2702f5 Mon Sep 17 00:00:00 2001 From: Alan Maynard Date: Fri, 29 Mar 2019 19:02:16 -0400 Subject: [PATCH 07/13] SWE-12 Use a nice slick animation - it appears that as a result of setting the target membership of `PaymentDetailInterfaceController` to only WKExtension has enabled this function call which was not working before --- .../PaymentDetailInterfaceController.swift | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentDetailInterfaceController.swift b/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentDetailInterfaceController.swift index 32df8da..161082c 100644 --- a/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentDetailInterfaceController.swift +++ b/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentDetailInterfaceController.swift @@ -43,13 +43,11 @@ class PaymentDetailInterfaceController: WKInterfaceController { self.popToRootController() } } else { -// animate(withDuration: 0.75) { -// self.paymentButton.setBackgroundColor(UIColor.init(red: 141, green: 241, blue: 48, alpha: 1.0)) -// } - - paymentButton.setBackgroundColor(#colorLiteral(red: 0.6092301607, green: 0.9366738796, blue: 0.2432599962, alpha: 1)) - paymentButtonArmed = true - paymentButton.setTitle("Pay Now") + animate(withDuration: 0.5) { + self.paymentButton.setBackgroundColor(#colorLiteral(red: 0.6092301607, green: 0.9366738796, blue: 0.2432599962, alpha: 1)) + self.paymentButtonArmed = true + self.paymentButton.setTitle("Pay Now") + } } } From 50d58635a2014339084d538c8edbe280072fa1ce Mon Sep 17 00:00:00 2001 From: Alan Maynard Date: Tue, 2 Apr 2019 19:15:19 -0400 Subject: [PATCH 08/13] SWE-12 Support for Disclaimer screen - also made IBOutlets `weak` to avoid retain cycles - we present an action sheet to the user which requires them to tape Pay Now to submit payment - activity indicator is shown until web service returns - if successful, we push to the payment result screen and show confirmation number, etc - if error, we ask the user to try again later --- .../Base.lproj/Interface.storyboard | 41 +++++++++++-------- .../PaymentDetailInterfaceController.swift | 41 ++++++++++++++----- .../PaymentResultInterfaceController.swift | 4 +- 3 files changed, 58 insertions(+), 28 deletions(-) diff --git a/SynchronyFinancial/SynchronyFinancial WatchKit App/Base.lproj/Interface.storyboard b/SynchronyFinancial/SynchronyFinancial WatchKit App/Base.lproj/Interface.storyboard index 4ccc998..26db9cf 100644 --- a/SynchronyFinancial/SynchronyFinancial WatchKit App/Base.lproj/Interface.storyboard +++ b/SynchronyFinancial/SynchronyFinancial WatchKit App/Base.lproj/Interface.storyboard @@ -199,24 +199,33 @@ - + + + @@ -247,7 +256,7 @@ - + diff --git a/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentDetailInterfaceController.swift b/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentDetailInterfaceController.swift index 161082c..18b312b 100644 --- a/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentDetailInterfaceController.swift +++ b/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentDetailInterfaceController.swift @@ -16,15 +16,21 @@ class PaymentDetailInterfaceController: WKInterfaceController { var paymentButtonArmed: Bool = false var paymentAmount: Double = 0.0 + @IBOutlet weak var contentGroup: WKInterfaceGroup! + @IBOutlet weak var activityIndicator: WKInterfaceImage! + @IBOutlet weak var activityIndicatorLabel: WKInterfaceLabel! @IBOutlet weak var detailButton: WKInterfaceButton! @IBOutlet weak var amount: WKInterfaceLabel! @IBOutlet weak var paymentButton: WKInterfaceButton! override func awake(withContext context: Any?) { super.awake(withContext: context) - guard let data = context as? [String: Any], let acct = data["acct"] as? Account, let amount = data["payment_amount"] as? Double else { - NSLog("Error getting account object and payment amount") - return + + guard let data = context as? [String: Any], + let acct = data["acct"] as? Account, + let amount = data["payment_amount"] as? Double else { + NSLog("Error getting account object and payment amount") + return } self.paymentAmount = amount @@ -35,13 +41,28 @@ class PaymentDetailInterfaceController: WKInterfaceController { @IBAction func paymentAction() { if paymentButtonArmed { guard let alias = selectedAccount?.accountAlias else { return } - FetchData.submitPayment(for: alias, type: "CBL", amount: 20.00, bankID: "9999") { confirmationNum, paymentID, error in - guard error == nil else { return } - self.dictForPayment.updateValue(confirmationNum, forKey: "payment_confirmation_number") - self.dictForPayment.updateValue(paymentID, forKey: "payment_id") - self.presentController(withName: "PaymentResult", context: self.dictForPayment) - self.popToRootController() - } + let cancel = WKAlertAction(title: "Cancel", style: .cancel, handler: {}) + let submit = WKAlertAction(title: "Pay Now", style: .default, handler: { + self.contentGroup.setHidden(true) + self.activityIndicator.configureForActivityIndicator() + self.activityIndicatorLabel.setHidden(false) + self.activityIndicatorLabel.setVerticalAlignment(.center) + FetchData.submitPayment(for: alias, type: "CBL", amount: 20.00, bankID: "9999") { confirmationNum, paymentID, error in + guard error == nil else { + let dismiss = WKAlertAction(title: "Dismiss", style: .cancel, handler: {}) + self.presentAlert(withTitle: "Error", message: "We were unable to process your payment at this time. Please try again later.", preferredStyle: .alert, actions: [dismiss]) + return + } + self.dictForPayment.updateValue(confirmationNum, forKey: "payment_confirmation_number") + self.dictForPayment.updateValue(paymentID, forKey: "payment_id") + self.activityIndicator.stopAnimatingAsIndicator() + self.activityIndicatorLabel.setHidden(true) + self.contentGroup.setHidden(false) + self.presentController(withName: "PaymentResult", context: self.dictForPayment) + self.popToRootController() + } + }) + presentAlert(withTitle: "Disclaimer", message: "By tapping \"Pay Now\", you are authorizing Synchrony Bank to process a one time payment in the amount of \(String(format: "$%.2f", paymentAmount)).", preferredStyle: .actionSheet, actions: [cancel, submit]) } else { animate(withDuration: 0.5) { self.paymentButton.setBackgroundColor(#colorLiteral(red: 0.6092301607, green: 0.9366738796, blue: 0.2432599962, alpha: 1)) diff --git a/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentResultInterfaceController.swift b/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentResultInterfaceController.swift index 6bf3c42..d93a30d 100644 --- a/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentResultInterfaceController.swift +++ b/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentResultInterfaceController.swift @@ -10,8 +10,8 @@ import WatchKit import Foundation class PaymentResultInterfaceController: WKInterfaceController { - @IBOutlet var confirmationNumberLabel: WKInterfaceLabel! - @IBOutlet var paymentIDLabel: WKInterfaceLabel! + @IBOutlet weak var confirmationNumberLabel: WKInterfaceLabel! + @IBOutlet weak var paymentIDLabel: WKInterfaceLabel! override func awake(withContext context: Any?) { super.awake(withContext: context) From 5407b6962b74498d76379923595db217fac773b0 Mon Sep 17 00:00:00 2001 From: Alan Maynard Date: Thu, 4 Apr 2019 20:32:55 -0400 Subject: [PATCH 09/13] SWE-12 swiftlint warning cleanup, payment fine tweaks - created new `enum PaymentType` to provide a cleaner way to pass code for either current balance payment or minimum due payment --- .../FetchData.swift | 18 ++++++++---------- .../PaymentDetailInterfaceController.swift | 5 ++++- .../SynchronyFinancial/Transaction.swift | 5 +++++ 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/SynchronyFinancial/SynchronyFinancial WatchKit Extension/FetchData.swift b/SynchronyFinancial/SynchronyFinancial WatchKit Extension/FetchData.swift index 3f23de7..cc5413d 100644 --- a/SynchronyFinancial/SynchronyFinancial WatchKit Extension/FetchData.swift +++ b/SynchronyFinancial/SynchronyFinancial WatchKit Extension/FetchData.swift @@ -90,7 +90,7 @@ class FetchData { case .success(let value): let dict = JSON(value).dictionaryValue guard dict["status"]?.dictionaryValue["response_code"]?.string == "0" else { return } - + //let's first parse the pending transactions dict["pending_transaction_list"]?.arrayValue.forEach { if let desc = $0["description"].string, @@ -103,11 +103,11 @@ class FetchData { let modifiable = $0["is_payment_modifiable"].string { let type: TransactionType = $0["payment_amount_type"].stringValue == "" ? .purchase : .reimbursement let isModifiable: Bool = modifiable == "Y" ? true : false - + transactions.append(Transaction(type: type, amount: amount, merchantID: desc, date: date, confirmationNum: confirmationNum, paymentId: paymentId, isPending: true, isModifiable: isModifiable)) } } - + // let's parse just processed transactions now dict["processed_transaction_list"]?.arrayValue.forEach { if let desc = $0["description"].string, @@ -125,7 +125,7 @@ class FetchData { } } } - + static func getBankInfo(completion: @escaping ([BankAcct], Error?) -> Void) { var bankIds: [BankAcct] = [] Alamofire.request(Defaults.FETCH_BANKS_URL, method: .post, parameters: Defaults.headerForMulti, encoding: JSONEncoding.default, headers: Defaults.authHeader).responseJSON { payload in @@ -151,14 +151,13 @@ class FetchData { } } } - + static func cancelPayment(accountAlias: String, confirmationNum: String, paymentId: Int, completion: @escaping (String, Error?) -> Void){ - var paymentHeader = Defaults.headerForCancelPmt paymentHeader["account_alias"] = accountAlias paymentHeader["payment_confirmation_number"] = confirmationNum paymentHeader["payment_id"] = paymentId - + Alamofire.request(Defaults.CANCEL_PAYMENT_URL, method: .post, parameters: paymentHeader, encoding: JSONEncoding.default, headers: Defaults.authHeader).responseJSON { payload in switch payload.result { case .success(let value): @@ -173,15 +172,14 @@ class FetchData { } } - static func submitPayment(for alias: String, type: String, amount: Double, bankID: String, completion: @escaping (String, String, Error?) -> Void) { + static func submitPayment(for alias: String, type: PaymentType, amount: Double, bankID: String, completion: @escaping (String, String, Error?) -> Void) { var paymentHeader = Defaults.headerForPmt paymentHeader["account_alias"] = alias paymentHeader["bank_account_id"] = bankID - paymentHeader["payment_amount_type"] = type + paymentHeader["payment_amount_type"] = type.rawValue paymentHeader["payment_amount"] = amount paymentHeader["scheduled_payment_post_date"] = Defaults.careCreditDateFormatter.string(from: Date()) - Alamofire.request(Defaults.MAKE_PAYMENT_URL, method: .post, parameters: paymentHeader, encoding: JSONEncoding.default, headers: Defaults.authHeader).responseJSON { payload in switch payload.result { case .success(let value): diff --git a/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentDetailInterfaceController.swift b/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentDetailInterfaceController.swift index 18b312b..99ab3b1 100644 --- a/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentDetailInterfaceController.swift +++ b/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentDetailInterfaceController.swift @@ -47,7 +47,10 @@ class PaymentDetailInterfaceController: WKInterfaceController { self.activityIndicator.configureForActivityIndicator() self.activityIndicatorLabel.setHidden(false) self.activityIndicatorLabel.setVerticalAlignment(.center) - FetchData.submitPayment(for: alias, type: "CBL", amount: 20.00, bankID: "9999") { confirmationNum, paymentID, error in + let type: PaymentType = self.paymentAmount == self.selectedAccount?.curBalance ? .currentBal : .minimumDue + + // process this payment using default bank account (9999) until ability to change account is implemented + FetchData.submitPayment(for: alias, type: type, amount: self.paymentAmount, bankID: "9999") { confirmationNum, paymentID, error in guard error == nil else { let dismiss = WKAlertAction(title: "Dismiss", style: .cancel, handler: {}) self.presentAlert(withTitle: "Error", message: "We were unable to process your payment at this time. Please try again later.", preferredStyle: .alert, actions: [dismiss]) diff --git a/SynchronyFinancial/SynchronyFinancial/Transaction.swift b/SynchronyFinancial/SynchronyFinancial/Transaction.swift index 71c58b0..e24c2b3 100644 --- a/SynchronyFinancial/SynchronyFinancial/Transaction.swift +++ b/SynchronyFinancial/SynchronyFinancial/Transaction.swift @@ -12,6 +12,11 @@ public enum TransactionType: Int { case reimbursement = 1 } +public enum PaymentType: String { + case currentBal = "CBL" + case minimumDue = "MIN" +} + class Transaction: NSObject { var type: TransactionType var amount: Double From fff4ae06c1dddac29946fa9005173db1ea7b24a4 Mon Sep 17 00:00:00 2001 From: Alan Maynard Date: Thu, 4 Apr 2019 20:36:01 -0400 Subject: [PATCH 10/13] SWE-12 disable payment buttons in given situations - if the minimum payment due is $0, we disable the button to allow paying that amount - if the current account balance is $0, we disable the button to allow paying that amount --- .../PayBillInterfaceController.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PayBillInterfaceController.swift b/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PayBillInterfaceController.swift index 3593120..5facc30 100644 --- a/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PayBillInterfaceController.swift +++ b/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PayBillInterfaceController.swift @@ -60,6 +60,9 @@ class PayBillInterfaceController: WKInterfaceController { let minimumFormatted = String(format: "$%.2f", valid.minPayDue) minimumLabel.setText("Minimum Payment:\n\(minimumFormatted)") payMinimumButton.setTitle("Pay \(minimumFormatted)") + + payMinimumButton.setEnabled(valid.minPayDue > 0.0) + payBalanceButton.setEnabled(valid.curBalance > 0.0) } } } From ed55a49e095c298490e72608c08ab9958a2e5116 Mon Sep 17 00:00:00 2001 From: Alan Maynard Date: Thu, 4 Apr 2019 20:47:31 -0400 Subject: [PATCH 11/13] =?UTF-8?q?SWE-12=20Remove=20unused=20=E2=80=9CHome?= =?UTF-8?q?=E2=80=9D=20button?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - we now simply display “Done” as the title to dismiss the payment result screen which is presented modally --- .../Base.lproj/Interface.storyboard | 11 +++-------- .../PaymentResultInterfaceController.swift | 5 +---- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/SynchronyFinancial/SynchronyFinancial WatchKit App/Base.lproj/Interface.storyboard b/SynchronyFinancial/SynchronyFinancial WatchKit App/Base.lproj/Interface.storyboard index 492ace8..c2bdbb3 100644 --- a/SynchronyFinancial/SynchronyFinancial WatchKit App/Base.lproj/Interface.storyboard +++ b/SynchronyFinancial/SynchronyFinancial WatchKit App/Base.lproj/Interface.storyboard @@ -243,14 +243,9 @@