From 962e8d21ca0a2f6d737383a97776c0a6fd89604e Mon Sep 17 00:00:00 2001 From: Danilo Joksimovic <32694765+djoksimo@users.noreply.github.com> Date: Thu, 9 May 2024 11:19:41 -0400 Subject: [PATCH] [FX-1362] Only grab the payment_method ref from the ThinPayment (#163) * Only grab the payment_method ref from the ThinPayment * Update unit tests --- .../Network/LiveForageService.swift | 10 +++++--- .../Network/Model/PaymentModel.swift | 14 +++++++++++ .../Network/Protocol/ForageService.swift | 4 ++-- Tests/ForageSDKTests/ForageServiceTests.swift | 24 +++++++++++++++++-- 4 files changed, 45 insertions(+), 7 deletions(-) diff --git a/Sources/ForageSDK/Foundation/Network/LiveForageService.swift b/Sources/ForageSDK/Foundation/Network/LiveForageService.swift index 30e26f16..3a4886b7 100644 --- a/Sources/ForageSDK/Foundation/Network/LiveForageService.swift +++ b/Sources/ForageSDK/Foundation/Network/LiveForageService.swift @@ -274,7 +274,11 @@ class LiveForageService: ForageService { private func getTokenFromPayment(sessionToken: String, merchantID: String, paymentRef: String) async throws -> String { do { - let payment = try await awaitResult { completion in + /// We only decode what we need here using `ThinPaymentModel` + /// (e.g. the associated `paymentMethodRef`) + /// beacuse many of the `PaymentModel` properties (e.g. `amount`) may be `nil` + /// until the Payment is updated and captured. + let payment: ThinPaymentModel = try await awaitResult { completion in self.getPayment( sessionToken: sessionToken, merchantID: merchantID, @@ -306,8 +310,8 @@ class LiveForageService: ForageService { } } - internal func getPayment(sessionToken: String, merchantID: String, paymentRef: String, completion: @escaping (Result) -> Void) { - do { try provider.execute(model: PaymentModel.self, endpoint: ForageAPI.getPayment(sessionToken: sessionToken, merchantID: merchantID, paymentRef: paymentRef), completion: completion) } catch { completion(.failure(error)) } + internal func getPayment(sessionToken: String, merchantID: String, paymentRef: String, completion: @escaping (Result) -> Void) { + do { try provider.execute(model: T.self, endpoint: ForageAPI.getPayment(sessionToken: sessionToken, merchantID: merchantID, paymentRef: paymentRef), completion: completion) } catch { completion(.failure(error)) } } internal func getPaymentMethod( diff --git a/Sources/ForageSDK/Foundation/Network/Model/PaymentModel.swift b/Sources/ForageSDK/Foundation/Network/Model/PaymentModel.swift index 08d4d9ef..ad802f5b 100644 --- a/Sources/ForageSDK/Foundation/Network/Model/PaymentModel.swift +++ b/Sources/ForageSDK/Foundation/Network/Model/PaymentModel.swift @@ -105,3 +105,17 @@ public struct PaymentModel: Codable { case error } } + +/// When using the deferred capture flow +/// the Payment may not have some `null` properties +/// (`amount`, `delivery_address`, `is_delivery`, ...) until the +/// payment is updated and captured on the server-side. +/// In turn, we only grab what we need from `ThinPaymentModel` for +/// intermediate internal SDK requests to `GET /payments/` +internal struct ThinPaymentModel: Codable { + internal let paymentMethodRef: String + + private enum CodingKeys: String, CodingKey { + case paymentMethodRef = "payment_method" + } +} diff --git a/Sources/ForageSDK/Foundation/Network/Protocol/ForageService.swift b/Sources/ForageSDK/Foundation/Network/Protocol/ForageService.swift index eb5976cb..12a34747 100644 --- a/Sources/ForageSDK/Foundation/Network/Protocol/ForageService.swift +++ b/Sources/ForageSDK/Foundation/Network/Protocol/ForageService.swift @@ -49,11 +49,11 @@ protocol ForageService: AnyObject { /// - merchantID: The unique ID of the Merchant. /// - paymentRef: The reference hash of the Payment. /// - completion: The closure returns a `Result` containing either a `PaymentModel` or an `Error`. [Read more](https://docs.joinforage.app/reference/get-payment-details) - func getPayment( + func getPayment( sessionToken: String, merchantID: String, paymentRef: String, - completion: @escaping (Result) -> Void + completion: @escaping (Result) -> Void ) /// Tokenize an EBT card using the given *ForagePANRequestModel* object diff --git a/Tests/ForageSDKTests/ForageServiceTests.swift b/Tests/ForageSDKTests/ForageServiceTests.swift index 6fa41b72..00badfa0 100644 --- a/Tests/ForageSDKTests/ForageServiceTests.swift +++ b/Tests/ForageSDKTests/ForageServiceTests.swift @@ -184,7 +184,7 @@ final class ForageServiceTests: XCTestCase { let service = createTestService(mockSession) let expectation = XCTestExpectation(description: "Get the Payment - should succeed") - service.getPayment(sessionToken: "auth1234", merchantID: "1234567", paymentRef: "11767381fd") { result in + service.getPayment(sessionToken: "auth1234", merchantID: "1234567", paymentRef: "11767381fd") { (result: Result) in switch result { case let .success(payment): XCTAssertEqual(payment.paymentMethodRef, "81dab02290") @@ -199,6 +199,26 @@ final class ForageServiceTests: XCTestCase { } wait(for: [expectation], timeout: 1.0) } + + func test_getThinPayment_onSuccess_checkExpectedPayload() { + let mockSession = URLSessionMock() + mockSession.data = forageMocks.capturePaymentSuccess + mockSession.response = forageMocks.mockSuccessResponse + let service = createTestService(mockSession) + + let expectation = XCTestExpectation(description: "Get the Payment - should succeed") + service.getPayment(sessionToken: "auth1234", merchantID: "1234567", paymentRef: "11767381fd") { (result: Result) in + switch result { + case let .success(payment): + XCTAssertEqual(payment.paymentMethodRef, "81dab02290") + expectation.fulfill() + case .failure: + XCTFail("Expected success") + } + } + wait(for: [expectation], timeout: 1.0) + } + func test_getPayment_onFailure_shouldReturnFailure() { let mockSession = URLSessionMock() @@ -207,7 +227,7 @@ final class ForageServiceTests: XCTestCase { let service = createTestService(mockSession) let expectation = XCTestExpectation(description: "Get the Payment - result should be failure") - service.getPayment(sessionToken: "auth1234", merchantID: "1234567", paymentRef: "11767381fd") { result in + service.getPayment(sessionToken: "auth1234", merchantID: "1234567", paymentRef: "11767381fd") { (result: Result) in switch result { case .success: XCTFail("Expected failure")