From 3ae9792f3f11ca65f2f2c012069ef8c026e15f9b Mon Sep 17 00:00:00 2001 From: Alan Maynard Date: Fri, 29 Mar 2019 18:38:20 -0400 Subject: [PATCH 01/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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 ce07b1f589f55b9882eb040ad4fa636a1090ba0b Mon Sep 17 00:00:00 2001 From: Alan Maynard Date: Tue, 2 Apr 2019 20:18:52 -0400 Subject: [PATCH 09/15] SWE-23 Implement modal view to show transaction details MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - preliminary design for screen to “pop up” and show transaction details - opted for a more robust approach than a simple `WKAlert` in order to have multiple labels for values such as date, amount, etc - Cancel Payment button hides/shows for qualifying transactions --- .../Base.lproj/Interface.storyboard | 23 ++++++++++ ...ransactionDetailsInterfaceController.swift | 46 +++++++++++++++++++ .../TransactionsInterfaceController.swift | 10 ++++ .../project.pbxproj | 4 ++ 4 files changed, 83 insertions(+) create mode 100644 SynchronyFinancial/SynchronyFinancial WatchKit Extension/TransactionDetailsInterfaceController.swift diff --git a/SynchronyFinancial/SynchronyFinancial WatchKit App/Base.lproj/Interface.storyboard b/SynchronyFinancial/SynchronyFinancial WatchKit App/Base.lproj/Interface.storyboard index ed397d2..aec54b4 100644 --- a/SynchronyFinancial/SynchronyFinancial WatchKit App/Base.lproj/Interface.storyboard +++ b/SynchronyFinancial/SynchronyFinancial WatchKit App/Base.lproj/Interface.storyboard @@ -253,6 +253,29 @@ + + + + + + + + diff --git a/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentResultInterfaceController.swift b/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentResultInterfaceController.swift index d93a30d..3208d1c 100644 --- a/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentResultInterfaceController.swift +++ b/SynchronyFinancial/SynchronyFinancial WatchKit Extension/PaymentResultInterfaceController.swift @@ -21,13 +21,10 @@ class PaymentResultInterfaceController: WKInterfaceController { let paymentID = data["payment_id"] { confirmationNumberLabel.setText(paymentConfirmation) paymentIDLabel.setText(paymentID) + setTitle("Done") } } - @IBAction func didTapHome() { - popToRootController() - } - override func willActivate() { // This method is called when watch view controller is about to be visible to user super.willActivate() From d4bf1b82b1c09411a67607a740f77ad2348663cd Mon Sep 17 00:00:00 2001 From: Alan Maynard Date: Thu, 4 Apr 2019 20:47:54 -0400 Subject: [PATCH 13/15] SWE-12 [swiftlint] resolve swiftlint warnings --- .../SynchronyFinancial WatchKit Extension/FetchData.swift | 2 +- .../SynchronyFinancial WatchKit Extension/TransactionCell.swift | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/SynchronyFinancial/SynchronyFinancial WatchKit Extension/FetchData.swift b/SynchronyFinancial/SynchronyFinancial WatchKit Extension/FetchData.swift index cc5413d..e531c63 100644 --- a/SynchronyFinancial/SynchronyFinancial WatchKit Extension/FetchData.swift +++ b/SynchronyFinancial/SynchronyFinancial WatchKit Extension/FetchData.swift @@ -152,7 +152,7 @@ class FetchData { } } - static func cancelPayment(accountAlias: String, confirmationNum: String, paymentId: Int, completion: @escaping (String, Error?) -> Void){ + 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 diff --git a/SynchronyFinancial/SynchronyFinancial WatchKit Extension/TransactionCell.swift b/SynchronyFinancial/SynchronyFinancial WatchKit Extension/TransactionCell.swift index e9d39bd..8825369 100644 --- a/SynchronyFinancial/SynchronyFinancial WatchKit Extension/TransactionCell.swift +++ b/SynchronyFinancial/SynchronyFinancial WatchKit Extension/TransactionCell.swift @@ -10,7 +10,6 @@ import Foundation import WatchKit class TransactionCell: NSObject { - @IBOutlet weak var transactionLabel: WKInterfaceLabel! @IBOutlet weak var valueLabel: WKInterfaceLabel! } From be8b0cfda9e504639636bb61f9390950e9f4a47c Mon Sep 17 00:00:00 2001 From: Alan Maynard Date: Thu, 4 Apr 2019 21:01:36 -0400 Subject: [PATCH 14/15] SWE-12 use new date formatter - several commits ago we created `careCreditDateFormatter` - replace usage of regular `DateFormatter` which require setting of format style and locale in each instance to `static` property which automatically returns the date formatter we want --- .../FetchData.swift | 12 +++--------- SynchronyFinancial/SynchronyFinancial/Defaults.swift | 8 ++------ 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/SynchronyFinancial/SynchronyFinancial WatchKit Extension/FetchData.swift b/SynchronyFinancial/SynchronyFinancial WatchKit Extension/FetchData.swift index e531c63..5426ea7 100644 --- a/SynchronyFinancial/SynchronyFinancial WatchKit Extension/FetchData.swift +++ b/SynchronyFinancial/SynchronyFinancial WatchKit Extension/FetchData.swift @@ -43,9 +43,6 @@ class FetchData { guard dict["status"]?.dictionaryValue["response_code"]?.string == "0" else { return } //print(json) - let formatter = DateFormatter() - formatter.locale = Locale.current - formatter.dateFormat = "yyyyMMdd" if let accounts = dict["account_number_list"]?.arrayValue { accounts.forEach { if let accountAlias = $0.dictionaryValue["account_alias"]?.string, @@ -53,7 +50,7 @@ class FetchData { let creditLimitString = $0.dictionaryValue["credit_limit"]?.string, let creditLimit = Double(creditLimitString), let payDueDateString = $0.dictionaryValue["next_payment_due_date"]?.string, - let paymentDueDate = formatter.date(from: payDueDateString), + let paymentDueDate = Defaults.careCreditDateFormatter.date(from: payDueDateString), let curBalString = $0.dictionaryValue["current_balance"]?.string, let currentBalance = Double(curBalString), let availCreditString = $0.dictionaryValue["available_credit"]?.string, @@ -81,9 +78,6 @@ class FetchData { var header = Defaults.headerForTransaction header["account_alias"] = accountAlias var transactions: [Transaction] = [] - let formatter = DateFormatter() - formatter.locale = Locale.current - formatter.dateFormat = "yyyyMMdd" Alamofire.request(Defaults.TRANS_HISTORY_URL, method: .post, parameters: header, encoding: JSONEncoding.default, headers: Defaults.authHeader).responseJSON { payload in switch payload.result { @@ -94,7 +88,7 @@ class FetchData { //let's first parse the pending transactions dict["pending_transaction_list"]?.arrayValue.forEach { if let desc = $0["description"].string, - let date = formatter.date(from: $0["transaction_date"].stringValue), + let date = Defaults.careCreditDateFormatter.date(from: $0["transaction_date"].stringValue), let amountString = $0["transaction_amount"].string, let amount = Double(amountString), let confirmationNum = $0["payment_confirmation_number"].string, @@ -111,7 +105,7 @@ class FetchData { // let's parse just processed transactions now dict["processed_transaction_list"]?.arrayValue.forEach { if let desc = $0["description"].string, - let date = formatter.date(from: $0["transaction_date"].stringValue), + let date = Defaults.careCreditDateFormatter.date(from: $0["transaction_date"].stringValue), let amountString = $0["transaction_amount"].string, let amount = Double(amountString) { let type: TransactionType = $0["payment_amount_type"].stringValue == "" ? .purchase : .reimbursement diff --git a/SynchronyFinancial/SynchronyFinancial/Defaults.swift b/SynchronyFinancial/SynchronyFinancial/Defaults.swift index 6da079f..55958a8 100644 --- a/SynchronyFinancial/SynchronyFinancial/Defaults.swift +++ b/SynchronyFinancial/SynchronyFinancial/Defaults.swift @@ -54,13 +54,9 @@ final class Defaults { var account_alias = "" // Dates - let formatter = DateFormatter() - formatter.locale = Locale.current - formatter.dateFormat = "yyyyMMdd" - // for now lets get transactions from the past 2 weeks - let start_date = formatter.string(from: Calendar.current.date(byAdding: .day, value: -14, to: Date()) ?? Date()) - let end_date = formatter.string(from: Date()) + let start_date = careCreditDateFormatter.string(from: Calendar.current.date(byAdding: .day, value: -14, to: Date()) ?? Date()) + let end_date = careCreditDateFormatter.string(from: Date()) return ["account_alias": account_alias, "begin_sequence": "1", From 9c5c0b105b447bb071a5949055f8496790616787 Mon Sep 17 00:00:00 2001 From: Alan Maynard Date: Thu, 4 Apr 2019 21:11:08 -0400 Subject: [PATCH 15/15] SWE-23 change back button text --- .../Base.lproj/Interface.storyboard | 10 +++++++--- .../TransactionDetailsInterfaceController.swift | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/SynchronyFinancial/SynchronyFinancial WatchKit App/Base.lproj/Interface.storyboard b/SynchronyFinancial/SynchronyFinancial WatchKit App/Base.lproj/Interface.storyboard index aec54b4..82c68de 100644 --- a/SynchronyFinancial/SynchronyFinancial WatchKit App/Base.lproj/Interface.storyboard +++ b/SynchronyFinancial/SynchronyFinancial WatchKit App/Base.lproj/Interface.storyboard @@ -262,9 +262,13 @@ -