Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Add card validation logic for remote validation and co-badged cards #723

Merged
merged 21 commits into from
Nov 7, 2023
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
c1c44ed
Extend PrimerCardData with field for network id
jnewc Oct 30, 2023
5d6dd3c
Initial implementation of core remote card validation and request deb…
jnewc Oct 30, 2023
5fcb363
Setup mocks for unit tests + add initial test for checking sanity
jnewc Oct 31, 2023
9031393
Add tests for complex card entry and validation
jnewc Nov 1, 2023
9bdf223
Better names for sdk mock methods
jnewc Nov 1, 2023
dcca32e
Code cleanup and rename of bin data service
jnewc Nov 1, 2023
f56a859
Rename bin data service
jnewc Nov 1, 2023
e7376f1
further cleanup
jnewc Nov 1, 2023
cc3daa0
Fix guard logic based on manual testing
jnewc Nov 1, 2023
78b0ced
Add test for errors, refactor tests + ensure max 8 digits sent to bin…
jnewc Nov 2, 2023
7d2e7b5
Merge remote-tracking branch 'origin/master' into jn/co-badged-cards/…
jnewc Nov 2, 2023
d139d87
Re-add nolpay
jnewc Nov 2, 2023
a94d519
Firm up tests with multiple card numbers -> results and better expect…
jnewc Nov 2, 2023
2f2dac5
Merge branch 'feature/co-badged-cards' into jn/co-badged-cards/card-e…
jnewc Nov 2, 2023
40e6225
Cleanup tests + prevent existing tests from failing due to non-featur…
jnewc Nov 2, 2023
c847ab9
Merge branch 'feature/co-badged-cards' into jn/co-badged-cards/card-e…
jnewc Nov 3, 2023
4dfeb2e
pod install for new release
jnewc Nov 3, 2023
1fd3918
Make cardNetworkIdentifier field optional when init-ing PrimerCardData
jnewc Nov 6, 2023
ba37dfd
CardValidationState -> CardState
jnewc Nov 6, 2023
8701c2c
Merge branch 'feature/co-badged-cards' into jn/co-badged-cards/card-e…
jnewc Nov 7, 2023
eecc5e3
PrimerCardState -> PrimerCardNumberEntryState
jnewc Nov 7, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 11 additions & 16 deletions Debug App/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,21 @@ PODS:
- KlarnaMobileSDK (2.2.2):
- KlarnaMobileSDK/full (= 2.2.2)
- KlarnaMobileSDK/full (2.2.2)
- Primer3DS (2.0.0)
- Primer3DS (2.0.1)
- PrimerIPay88MYSDK (0.1.6)
- PrimerKlarnaSDK (1.0.4):
- KlarnaMobileSDK (= 2.2.2)
- PrimerNolPaySDK (0.1.0)
- PrimerSDK (2.18.0-b1):
- PrimerSDK/Core (= 2.18.0-b1)
- PrimerSDK/Core (2.18.0-b1)
- PrimerNolPaySDK (1.0.0)
- PrimerSDK (2.18.0):
- PrimerSDK/Core (= 2.18.0)
- PrimerSDK/Core (2.18.0)

DEPENDENCIES:
- IQKeyboardManagerSwift
- Primer3DS (~> 2.0.0)
- PrimerIPay88MYSDK (from `https://github.com/primer-io/primer-ipay88-sdk-ios.git`, branch `master`)
- PrimerKlarnaSDK
- PrimerNolPaySDK (from `https://github.com/primer-io/primer-nol-pay-sdk-ios.git`, branch `master`)
- PrimerNolPaySDK
- PrimerSDK (from `../`)

SPEC REPOS:
Expand All @@ -26,34 +26,29 @@ SPEC REPOS:
- KlarnaMobileSDK
- Primer3DS
- PrimerKlarnaSDK
- PrimerNolPaySDK

EXTERNAL SOURCES:
PrimerIPay88MYSDK:
:branch: master
:git: https://github.com/primer-io/primer-ipay88-sdk-ios.git
PrimerNolPaySDK:
:branch: master
:git: https://github.com/primer-io/primer-nol-pay-sdk-ios.git
PrimerSDK:
:path: "../"

CHECKOUT OPTIONS:
PrimerIPay88MYSDK:
:commit: e870b41ba067dfe6ad72ca5446260a4363f9f494
:git: https://github.com/primer-io/primer-ipay88-sdk-ios.git
PrimerNolPaySDK:
:commit: 886712516afebdcebb3bf65312ad9026680fe4b9
:git: https://github.com/primer-io/primer-nol-pay-sdk-ios.git

SPEC CHECKSUMS:
IQKeyboardManagerSwift: 12d89768845bb77b55cc092ecc2b1f9370f06b76
KlarnaMobileSDK: 23b44390d06c6e3a90b5325bea6c10bf97ac6044
Primer3DS: 109e46ed31726039b9fb0ee6e1a0948fda345b24
Primer3DS: 16a0c0d48d83dcfe9fc5c213338bf5d48eeeb1de
PrimerIPay88MYSDK: a3097799a9ced2db623b2d8a3fbc226be7051f20
PrimerKlarnaSDK: de4b8b8fda075e3e4ebbd4ab80bd141c76a30d85
PrimerNolPaySDK: 4dff49bddbf2cfa0aec4ac287c947b1f0e4cf42d
PrimerSDK: 96f02df6d33c0033d71fd4079ff59d18281271a9
PrimerNolPaySDK: fad754f5f70c9f2f84efce0e7a0efc34883b670a
PrimerSDK: 83dc58cfd5cd5de47edcfd05ebf82739d9d3bd1b

PODFILE CHECKSUM: 7d391710bcd64a12bbd1571cfef36555eed30b2a
PODFILE CHECKSUM: def317e23d2ff3bba699f785bb325036d8198908

COCOAPODS: 1.13.0
98 changes: 65 additions & 33 deletions Debug App/Primer.io Debug App.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ class MerchantHeadlessCheckoutRawDataViewController: UIViewController {
var paymentMethodType: String!
var paymentId: String?
var activityIndicator: UIActivityIndicatorView?
var rawCardData = PrimerCardData(cardNumber: "", expiryDate: "", cvv: "", cardholderName: "")
var rawCardData = PrimerCardData(cardNumber: "",
expiryDate: "",
cvv: "",
cardholderName: "")
jnewc marked this conversation as resolved.
Show resolved Hide resolved

var cardnumberTextField: UITextField?
var expiryDateTextField: UITextField?
Expand Down Expand Up @@ -193,28 +196,32 @@ extension MerchantHeadlessCheckoutRawDataViewController: UITextFieldDelegate {
cardNumber: newText.replacingOccurrences(of: " ", with: ""),
expiryDate: self.expiryDateTextField?.text ?? "",
cvv: self.cvvTextField?.text ?? "",
cardholderName: self.cardholderNameTextField?.text ?? "")
cardholderName: self.cardholderNameTextField?.text ?? "",
cardNetworkIdentifier: self.rawCardData.cardNetworkIdentifier)

} else if textField == self.expiryDateTextField {
self.rawCardData = PrimerCardData(
cardNumber: self.cardnumberTextField?.text ?? "",
expiryDate: newText,
cvv: self.cvvTextField?.text ?? "",
cardholderName: self.cardholderNameTextField?.text ?? "")
cardholderName: self.cardholderNameTextField?.text ?? "",
cardNetworkIdentifier: self.rawCardData.cardNetworkIdentifier)

} else if textField == self.cvvTextField {
self.rawCardData = PrimerCardData(
cardNumber: self.cardnumberTextField?.text ?? "",
expiryDate: self.expiryDateTextField?.text ?? "",
cvv: newText,
cardholderName: self.cardholderNameTextField?.text ?? "")
cardholderName: self.cardholderNameTextField?.text ?? "",
cardNetworkIdentifier: self.rawCardData.cardNetworkIdentifier)

} else if textField == self.cardholderNameTextField {
self.rawCardData = PrimerCardData(
cardNumber: self.cardnumberTextField?.text ?? "",
expiryDate: self.expiryDateTextField?.text ?? "",
cvv: self.cvvTextField?.text ?? "",
cardholderName: newText.count == 0 ? nil : newText)
cardholderName: newText.count == 0 ? nil : newText,
cardNetworkIdentifier: self.rawCardData.cardNetworkIdentifier)
}

print("self.rawCardData\ncardNumber: \(self.rawCardData.cardNumber)\nexpiryDate: \(self.rawCardData.expiryDate)\ncvv: \(self.rawCardData.cvv)\ncardholderName: \(self.rawCardData.cardholderName ?? "nil")")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//
// MockRawDataManagerDelegate.swift
// Debug App Tests
//
// Created by Jack Newcombe on 31/10/2023.
// Copyright © 2023 Primer API Ltd. All rights reserved.
//

import Foundation
@testable import PrimerSDK

class MockRawDataManagerDelegate: RawDataManager.Delegate {

// MARK: metadataDidChange

var onMetadataDidChange: ((RawDataManager, [String: Any]?) -> Void)?

func primerRawDataManager(_ rawDataManager: RawDataManager,
metadataDidChange metadata: [String : Any]?) {
onMetadataDidChange?(rawDataManager, metadata)
}

// MARK: dataIsValid

var onDataIsValid: ((RawDataManager, Bool, [Error]?) -> Void)?

func primerRawDataManager(_ rawDataManager: RawDataManager,
dataIsValid isValid: Bool, errors: [Error]?) {
onDataIsValid?(rawDataManager, isValid, errors)
}

// MARK: willFetchCardMetadataForState

var onWillFetchCardMetadataForState: ((RawDataManager, PrimerCardValidationState) -> Void)?

var onWillFetchCardMetadataForStateCount = 0

func primerRawDataManager(_ rawDataManager: RawDataManager,
willFetchCardMetadataForState cardState: PrimerCardValidationState) {
onWillFetchCardMetadataForStateCount += 1
onWillFetchCardMetadataForState?(rawDataManager, cardState)
}

// MARK: metadata forCardValidationState

var onMetadataForCardValidationState: ((RawDataManager, PrimerCardMetadata, PrimerCardValidationState) -> Void)?

var onMetadataForCardValidationStateCount = 0

func primerRawDataManager(_ rawDataManager: RawDataManager,
didReceiveCardMetadata metadata: PrimerCardMetadata,
forCardValidationState cardState: PrimerCardValidationState) {
onMetadataForCardValidationStateCount += 1
onMetadataForCardValidationState?(rawDataManager, metadata, cardState)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//
// MockBINDataAPIClient.swift
// Debug App Tests
//
// Created by Jack Newcombe on 31/10/2023.
// Copyright © 2023 Primer API Ltd. All rights reserved.
//

import Foundation
@testable import PrimerSDK

class MockBINDataAPIClient: PrimerAPIClientBINDataProtocol {

class AnyCancellable: PrimerCancellable {
let canceller: () -> Void

var isCancelled = false

init(_ canceller: @escaping () -> Void) {
self.canceller = canceller
}

deinit {
canceller()
}

func cancel() {
canceller()
isCancelled = true
}
}

var results: [String: Response.Body.Bin.Networks] = [:]

var error: Error?

typealias ResponseCompletion = (Result<PrimerSDK.Response.Body.Bin.Networks, Error>) -> Void

func listCardNetworks(clientToken: PrimerSDK.DecodedJWTToken,
bin: String,
completion: @escaping ResponseCompletion) -> PrimerSDK.PrimerCancellable? {
let workItem = DispatchWorkItem { [self] in
if let error = error {
completion(.failure(error))
}
else if let result = results[bin] {
completion(.success(result))
}
}

let cancellable = AnyCancellable {
workItem.cancel()
}

DispatchQueue.main.asyncAfter(deadline: .now() + 0.25, execute: workItem)

return cancellable
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ class MockNetworkService: NetworkService {

var onReceiveEndpoint: ((Endpoint) -> Void)?

func request<T>(_ endpoint: PrimerSDK.Endpoint, completion: @escaping PrimerSDK.ResultCallback<T>) where T : Decodable {
func request<T>(_ endpoint: PrimerSDK.Endpoint,
completion: @escaping PrimerSDK.ResultCallback<T>) -> PrimerCancellable? where T : Decodable {

onReceiveEndpoint?(endpoint)

Expand All @@ -32,5 +33,7 @@ class MockNetworkService: NetworkService {
XCTFail("Failed to produce either a valid result or an error for requested endpoint")
}
}

return nil
}
}
Loading