Skip to content

Commit

Permalink
feat: add Risk package to pod dependencies
Browse files Browse the repository at this point in the history
refactor: move FD Risk implementation to Checkout module

refactor: move FD Risk package to Checkout target

feat: add tests for FD Risk

feat: update FD Risk test

feat: update FD Risk test

feat: update RiskSDK version(1.1.0)

refactor

chore: update Risk version

chore: update RiskSDK version

chore: update Risk version in Checkout podspec

Add privacy Info

Update Code-QL to scan FrameTests

Update CodeQL file

chore: replace local with repo Frames-ios on SPM example

chore
  • Loading branch information
precious-ossai-cko authored and okhan-okbay-cko committed Feb 28, 2024
1 parent ccb8b88 commit 30b5cd3
Show file tree
Hide file tree
Showing 10 changed files with 209 additions and 47 deletions.
21 changes: 18 additions & 3 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,25 @@ jobs:
with:
languages: ${{ matrix.language }}
queries: security-and-quality

- name: Build
- name: Build Frames
run: |
xcodebuild -scheme Frames -destination "platform=iOS Simulator,name=iPhone 14 Pro,OS=latest"
- name: Perform CodeQL Analysis
- name: Build FramesTests
run: |
xcodebuild -scheme FramesTests -destination "platform=iOS Simulator,name=iPhone 14 Pro,OS=latest" test
- name: Build iOS Example Frame SPM
run: |
cd iOS\ Example\ Frame\ SPM
xcodebuild build -scheme iOS\ Example\ Frame -destination "platform=iOS Simulator,name=iPhone 14 Pro,OS=latest"
- name: Build UITest
run: |
cd iOS\ Example\ Frame\ SPM
xcodebuild -scheme UITest -destination "platform=iOS Simulator,name=iPhone 14 Pro,OS=latest"
# Perform analysis on the code
- name: Analyze code with CodeQL
uses: github/codeql-action/analyze@v2
1 change: 1 addition & 0 deletions Checkout.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ Pod::Spec.new do |s|
s.exclude_files = "Checkout/Samples/**"

s.dependency 'CheckoutEventLoggerKit', '~> 1.2.4'
s.dependency 'Risk', '2.0.1'

end
48 changes: 41 additions & 7 deletions Checkout/Source/Tokenisation/CheckoutAPIService.swift
Original file line number Diff line number Diff line change
@@ -1,26 +1,35 @@
//
// CheckoutAPIService.swift
//
//
//
// Created by Harry Brown on 23/11/2021.
//

import Foundation
import UIKit
import CheckoutEventLoggerKit
import Risk

public protocol CheckoutAPIProtocol {
func createToken(_ paymentSource: PaymentSource, completion: @escaping (Result<TokenDetails, TokenisationError.TokenRequest>) -> Void)
func createSecurityCodeToken(securityCode: String, completion: @escaping (Result<SecurityCodeResponse, TokenisationError.SecurityCodeError>) -> Void)
var correlationID: String { get }
}

protocol RiskProtocol: AnyObject {
func configure(completion: @escaping (Result<Void, RiskError.Configuration>) -> Void)
func publishData (cardToken: String?, completion: @escaping (Result<PublishRiskData, RiskError.Publish>) -> Void)
}

extension Risk: RiskProtocol {}

final public class CheckoutAPIService: CheckoutAPIProtocol {
private let requestExecutor: RequestExecuting
private let requestFactory: RequestProviding
private let tokenRequestFactory: TokenRequestProviding
private let tokenDetailsFactory: TokenDetailsProviding
private let logManager: LogManaging.Type
private var riskSDK: RiskProtocol

private let publicKey: String
private let environment: BaseURLProviding
Expand All @@ -41,7 +50,18 @@ final public class CheckoutAPIService: CheckoutAPIProtocol {
let tokenRequestFactory = TokenRequestFactory(cardValidator: cardValidator, decoder: snakeCaseJSONDecoder)
let tokenDetailsFactory = TokenDetailsFactory()
let logManager = LogManager.self


var riskEnvironment: RiskEnvironment
switch environment {
case .production:
riskEnvironment = .production
case .sandbox:
riskEnvironment = .sandbox
}

let riskConfig = RiskConfig(publicKey: publicKey, environment: riskEnvironment, framesMode: true)
let riskSDK = Risk.init(config: riskConfig)

logManager.setup(
environment: environment,
logger: CheckoutEventLogger(productName: Constants.Product.name),
Expand All @@ -57,7 +77,8 @@ final public class CheckoutAPIService: CheckoutAPIProtocol {
requestFactory: requestFactory,
tokenRequestFactory: tokenRequestFactory,
tokenDetailsFactory: tokenDetailsFactory,
logManager: logManager)
logManager: logManager,
riskSDK: riskSDK)
}

init(
Expand All @@ -67,7 +88,8 @@ final public class CheckoutAPIService: CheckoutAPIProtocol {
requestFactory: RequestProviding,
tokenRequestFactory: TokenRequestProviding,
tokenDetailsFactory: TokenDetailsProviding,
logManager: LogManaging.Type
logManager: LogManaging.Type,
riskSDK: RiskProtocol
) {
self.publicKey = publicKey
self.environment = environment
Expand All @@ -76,6 +98,7 @@ final public class CheckoutAPIService: CheckoutAPIProtocol {
self.tokenRequestFactory = tokenRequestFactory
self.tokenDetailsFactory = tokenDetailsFactory
self.logManager = logManager
self.riskSDK = riskSDK
}

/// The create token method tokenises the user’s card details.
Expand Down Expand Up @@ -126,12 +149,21 @@ final public class CheckoutAPIService: CheckoutAPIProtocol {
requestParameters,
responseType: TokenResponse.self,
responseErrorType: TokenisationError.ServerError.self
) { [tokenDetailsFactory, logManager, logTokenResponse] tokenResponseResult, httpURLResponse in
) { [riskSDK, tokenDetailsFactory, logManager, logTokenResponse] tokenResponseResult, httpURLResponse in
logTokenResponse(tokenResponseResult, httpURLResponse)

switch tokenResponseResult {
case .response(let tokenResponse):
let tokenDetails = tokenDetailsFactory.create(tokenResponse: tokenResponse)

riskSDK.configure { configurationResult in
switch configurationResult {
case .failure: break
case .success():
riskSDK.publishData(cardToken: tokenDetails.token) { _ in }
}
}

completion(.success(tokenDetails))
case .errorResponse(let errorResponse):
completion(.failure(.serverError(errorResponse)))
Expand Down Expand Up @@ -204,9 +236,11 @@ extension CheckoutAPIService {
requestParameters,
responseType: SecurityCodeResponse.self,
responseErrorType: TokenisationError.ServerError.self
) { [logManager, logSecurityCodeTokenResponse] tokenResponseResult, httpURLResponse in
logSecurityCodeTokenResponse(tokenResponseResult, httpURLResponse)
) { [weak self] tokenResponseResult, httpURLResponse in
guard let self else { return }

logSecurityCodeTokenResponse(tokenResponseResult: tokenResponseResult, httpURLResponse: httpURLResponse)

switch tokenResponseResult {
case .response(let tokenResponse):
completion(.success(tokenResponse))
Expand Down
28 changes: 28 additions & 0 deletions CheckoutTests/Stubs/StubRisk.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//
// StubRisk.swift
//
//
// Created by Precious Ossai on 20/02/2024.
//

import Foundation
@testable import Risk
@testable import Checkout

// swiftlint:disable large_tuple
class StubRisk: RiskProtocol {

var configureCalledCount = 0
var publishDataCalledCount = 0

func configure(completion: @escaping (Result<Void, RiskError.Configuration>) -> Void) {
configureCalledCount += 1
completion(.success(()))
}

func publishData (cardToken: String? = nil, completion: @escaping (Result<PublishRiskData, RiskError.Publish>) -> Void) {
publishDataCalledCount += 1
completion(.success(PublishRiskData(deviceSessionId: "dsid_testDeviceSessionId")))
}
}

10 changes: 8 additions & 2 deletions CheckoutTests/Tokenisation/CheckoutAPIServiceTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ final class CheckoutAPIServiceTests: XCTestCase {
private var stubRequestFactory: StubRequestFactory! = StubRequestFactory()
private var stubTokenRequestFactory: StubTokenRequestFactory! = StubTokenRequestFactory()
private var stubTokenDetailsFactory: StubTokenDetailsFactory! = StubTokenDetailsFactory()
private var stubRisk: StubRisk! = .init()


override func setUp() {
Expand All @@ -36,7 +37,8 @@ final class CheckoutAPIServiceTests: XCTestCase {
requestFactory: stubRequestFactory,
tokenRequestFactory: stubTokenRequestFactory,
tokenDetailsFactory: stubTokenDetailsFactory,
logManager: StubLogManager.self
logManager: StubLogManager.self,
riskSDK: stubRisk
)
}

Expand All @@ -49,6 +51,7 @@ final class CheckoutAPIServiceTests: XCTestCase {
stubTokenRequestFactory = nil
stubSecurityCodeRequestExecutor = nil
stubTokenDetailsFactory = nil
stubRisk = nil

super.tearDown()
}
Expand Down Expand Up @@ -90,6 +93,8 @@ final class CheckoutAPIServiceTests: XCTestCase {
.init(tokenID: "token", scheme: "visa", httpStatusCode: 200, serverError: nil)
))

XCTAssertEqual(stubRisk.configureCalledCount, 1)
XCTAssertEqual(stubRisk.publishDataCalledCount, 1)
XCTAssertEqual(result, .success(tokenDetails))
}

Expand Down Expand Up @@ -213,7 +218,8 @@ extension CheckoutAPIServiceTests {
requestFactory: stubRequestFactory,
tokenRequestFactory: stubTokenRequestFactory,
tokenDetailsFactory: stubTokenDetailsFactory,
logManager: StubLogManager.self
logManager: StubLogManager.self,
riskSDK: stubRisk
)
}

Expand Down
18 changes: 18 additions & 0 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,24 @@
"version" : "1.2.4"
}
},
{
"identity" : "checkout-risk-sdk-ios",
"kind" : "remoteSourceControl",
"location" : "https://github.com/checkout/checkout-risk-sdk-ios.git",
"state" : {
"revision" : "4823f05166dca8392a41b56b975515c7e0f1a8da",
"version" : "2.0.1"
}
},
{
"identity" : "fingerprintjs-pro-ios",
"kind" : "remoteSourceControl",
"location" : "https://github.com/fingerprintjs/fingerprintjs-pro-ios",
"state" : {
"revision" : "ceb8b845ec99727ee9f78869a51688c6daa16bd8",
"version" : "2.2.0"
}
},
{
"identity" : "phonenumberkit",
"kind" : "remoteSourceControl",
Expand Down
4 changes: 2 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ let package = Package(
exact: "3.5.9"),
.package(
url: "https://github.com/checkout/checkout-risk-sdk-ios.git",
exact: "1.0.2"),
exact: "2.0.1"),
.package(
url: "https://github.com/checkout/checkout-event-logger-ios-framework.git",
from: "1.2.4"
Expand All @@ -32,7 +32,6 @@ let package = Package(
dependencies: [
.product(name: "CheckoutEventLoggerKit",
package: "checkout-event-logger-ios-framework"),
.product(name: "Risk", package: "checkout-risk-sdk-ios"),
"PhoneNumberKit",
"Checkout"
],
Expand All @@ -47,6 +46,7 @@ let package = Package(
dependencies: [
.product(name: "CheckoutEventLoggerKit",
package: "checkout-event-logger-ios-framework"),
.product(name: "Risk", package: "checkout-risk-sdk-ios"),
],
path: "Checkout/Source"
),
Expand Down
59 changes: 59 additions & 0 deletions Source/Resources/PrivacyInfo.xcprivacy
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrivacyCollectedDataTypes</key>
<array>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>Device Model</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<false/>
<key>NSPrivacyCollectedDataTypeTracking</key>
<false/>
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAnalytics</string>
</array>
</dict>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>SDK Version</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<false/>
<key>NSPrivacyCollectedDataTypeTracking</key>
<false/>
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAnalytics</string>
</array>
</dict>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypeDeviceID</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<false/>
<key>NSPrivacyCollectedDataTypeTracking</key>
<false/>
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAnalytics</string>
</array>
</dict>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>SDK Lifecyle Events</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<false/>
<key>NSPrivacyCollectedDataTypeTracking</key>
<false/>
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAnalytics</string>
</array>
</dict>
</array>
<key>NSPrivacyTracking</key>
<false/>
</dict>
</plist>
27 changes: 3 additions & 24 deletions Source/UI/PaymentForm/Factory/PaymentFormFactory.swift
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import UIKit
import Checkout
import Risk

public enum PaymentFormFactory {

public static func buildViewController(configuration: PaymentFormConfiguration,
style: PaymentStyle,
completionHandler: @escaping (Result<TokenDetails, TokenisationError.TokenRequest>) -> Void) -> UIViewController {
Expand All @@ -19,29 +18,9 @@ public enum PaymentFormFactory {
billingFormStyle: style.billingFormStyle,
supportedSchemes: configuration.supportedSchemes)
viewModel.preventDuplicateCardholderInput()



let viewController = FramesPaymentViewController(viewModel: viewModel)
viewModel.cardTokenRequested = { result in
completionHandler(result)

if let cardToken = try? result.get().token {

var environment: RiskEnvironment
switch configuration.environment {
case .live:
environment = .prod
case .sandbox:
environment = .sandbox
}

let riskConfig = RiskConfig(publicKey: configuration.serviceAPIKey, environment: environment, framesMode: true)

Risk.getInstance(config: riskConfig) { riskInstance in
riskInstance?.publishData(cardToken: cardToken) { _ in}
}
}
}
viewModel.cardTokenRequested = completionHandler
logger.log(.paymentFormInitialised(environment: configuration.environment))
if #available(iOS 13.0, *) {
viewController.isModalInPresentation = true
Expand Down
Loading

0 comments on commit 30b5cd3

Please sign in to comment.