Skip to content

Commit

Permalink
Merge pull request #25 from checkout/refactor/risk-instance
Browse files Browse the repository at this point in the history
Refactor folder structure and risk instance management
  • Loading branch information
precious-ossai-cko authored Feb 28, 2024
2 parents bf5223f + f18c375 commit 4823f05
Show file tree
Hide file tree
Showing 29 changed files with 538 additions and 307 deletions.
4 changes: 2 additions & 2 deletions .github/partial-readmes/Installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ We've done our best to support the most common distribution methods on iOS. We a
let package = Package(
...
dependencies: [
.package(url: "https://github.com/checkout/checkout-risk-sdk-ios", from: "1.0.3")
.package(url: "https://github.com/checkout/checkout-risk-sdk-ios", from: "2.0.1")
]
...
)
Expand All @@ -34,7 +34,7 @@ platform :ios, '12.0'
use_frameworks!

target '<Your Target Name>' do
pod 'Risk', '~> 1.0.3'
pod 'Risk', '~> 2.0.1'
end
```

Expand Down
12 changes: 12 additions & 0 deletions .swiftpm/xcode/xcshareddata/xcschemes/Risk.xcscheme
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,18 @@
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "RiskTests"
BuildableName = "RiskTests"
BlueprintName = "RiskTests"
ReferencedContainer = "container:">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
Expand Down
9 changes: 4 additions & 5 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,10 @@ let package = Package(
dependencies: [
.package(
url: "https://github.com/fingerprintjs/fingerprintjs-pro-ios",
.exact("2.2.0")
),
exact: "2.2.0"),
.package(
url: "https://github.com/checkout/checkout-event-logger-ios-framework.git",
from: "1.2.4"
)
from: "1.2.4")
],
targets: [
.target(
Expand All @@ -36,7 +34,8 @@ let package = Package(
path: "Sources"),
.testTarget(
name: "RiskTests",
dependencies: ["Risk"])
dependencies: ["Risk"],
path: "Tests")
],
swiftLanguageVersions: [.v5]
)
172 changes: 111 additions & 61 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,56 +29,126 @@ The package helps collect device data for merchants with direct integration (sta
### Usage guide
1. Add `Risk` as a package dependency - _see [Installation guide](https://github.com/checkout/checkout-risk-sdk-ios/blob/main/.github/partial-readmes/Installation.md) on how to add our SDK in your iOS app via SPM or Cocoapods._
2. Obtain a public API key from [Checkout Dashboard](https://dashboard.checkout.com/developers/keys).
3. Initialise the package with the `getInstance` method passing in the required configuration (public API key and environment), then publish the device data with the `publishData` method, see example below.
```swift
// Example usage of package
let yourConfig = RiskConfig(publicKey: "pk_qa_xxx", environment: RiskEnvironment.qa)
3. Initialise the package Risk with the public API key and environment `Risk.init(config: yourConfig)` early-on.
<details>
<summary>Type definitions</summary>

```swift
public struct RiskConfig {
let publicKey: String
let environment: RiskEnvironment
let framesMode: Bool
Risk.getInstance(config: yourConfig) { riskInstance in
riskInstance?.publishData() { response in
print(response.deviceSessionId)
}
}
```
public init(publicKey: String, environment: RiskEnvironment, framesMode: Bool = false) {
self.publicKey = publicKey
self.environment = environment
self.framesMode = framesMode
}
}

### Public API
The package exposes two methods:
1. `getInstance` - This is a method that returns a singleton instance of Risk. When the method is called, preliminary checks are made to Checkout's internal API(s) that retrieves the public keys used to initialise the package used in collecting device data, if the checks fail or the merchant is disabled, nil will be returned, else, if the checks are successful, the `Risk` instance is returned to the consumer of the package which can now be used to publish the data with the `publishData` method.
public enum RiskEnvironment {
case qa
case sandbox
case production
}
```
</details>
4. Use the `configure` to complete your setup, then publish the device data within the closure with the `publishData` method.

<details>
<summary>Arguments</summary>
<details>
<summary>Type definitions</summary>

```swift
public struct RiskConfig {
public let publicKey: String
public let environment: RiskEnvironment
public let framesMode: Bool

public init(publicKey: String, environment: RiskEnvironment, framesMode: Bool = false) {
self.publicKey = publicKey
self.environment = environment
self.framesMode = framesMode
```swift
public struct PublishRiskData {
public let deviceSessionId: String
}
}

public enum RiskEnvironment {
case qa
case sandbox
case prod
}
```
</details>
public enum RiskError: LocalizedError, Equatable {
case configuration(Configuration)
case publish(Publish)
}

public enum RiskError {
case configuration(Configuration)
case publish(Publish)
}

public extension RiskError {
enum Configuration: LocalizedError {
case integrationDisabled
case couldNotRetrieveConfiguration
public var errorDescription: String? {
switch self {
case .integrationDisabled:
return "Integration disabled"
case .couldNotRetrieveConfiguration:
return "Error retrieving configuration"
}
}
}
enum Publish: LocalizedError {
case couldNotPublishRiskData
case couldNotPersisRiskData
case fingerprintServiceIsNotConfigured
public var errorDescription: String? {
switch self {
case .couldNotPublishRiskData:
return "Error publishing risk data"
case .couldNotPersisRiskData:
return "Error persisting risk data"
case .fingerprintServiceIsNotConfigured:
return "Fingerprint service is not configured. Please call configure() method first."
}
}
}
}
```
</details>

See example below:
```swift
import Risk

// Example usage of package
let yourConfig = RiskConfig(publicKey: "pk_qa_xxx", environment: RiskEnvironment.qa)

self.riskSDK = Risk.init(config: yourConfig)

self.riskSDK.configure { configurationResult in

switch configurationResult {
case .failure(let errorResponse):
print(errorResponse.localizedDescription)
case .success():
self.riskSDK.publishData { result in

switch result {
case .success(let response):
print(response.deviceSessionId)
case .failure(let errorResponse):
print(errorResponse.localizedDescription)
}
}
}

}
```

### Public API
Aside the instantiation via the `init` method, the package exposes two methods:
1. `configure` - This method completes your setup after initialisation. When the method is called, preliminary checks are made to Checkout's internal API(s) that retrieves other configurations required for collecting device data, if the checks fail or the merchant is disabled, the error is returned and logged, you can also see more information on your Xcode console while in development mode.
<details>
<summary>Responses</summary>
<summary>Type definitions</summary>

```swift
public class Risk {
public func configure(completion: @escaping (Result<Void, RiskError.Configuration>) -> Void) {
...

public func publishData(...) ... {
...
}
}
```
</details>
Expand All @@ -87,35 +157,15 @@ The package exposes two methods:
2. `publishData` - This is used to publish and persist the device data.

<details>
<summary>Arguments</summary>
<summary>Type definitions</summary>

```swift
public func publishData(cardToken: String? = nil, completion: @escaping (Result<PublishRiskData, RiskError>) -> Void) {
public func publishData (cardToken: String? = nil, completion: @escaping (Result<PublishRiskData, RiskError.Publish>) -> Void) {
...
}
```
</details>

<details>
<summary>Responses</summary>

```swift
public struct PublishRiskData {
public let deviceSessionId: String
}

public enum RiskError: Error, Equatable {
case description(String)

var localizedDescription: String {
switch self {
case .description(let errorMessage):
return errorMessage
}
}
}
```
</details>

### Additional Resources
<!-- TODO: Add website documentation link here - [Risk iOS SDK documentation](https://docs.checkout.com/risk/overview) -->
Expand Down
2 changes: 1 addition & 1 deletion Risk.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "Risk"
s.version = "1.0.3"
s.version = "2.0.1"
s.summary = "Checkout Risk package in Swift"
s.description = <<-DESC
Checkout Risk package in Swift.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Foundation

enum Constants {
static let productName = "risk-ios-sdk"
static let riskSdkVersion = "1.0.3"
static let riskSdkVersion = "2.0.1"
static let userAgent = "checkout-sdk-risk-ios/\(riskSdkVersion)"
static let loggerTypeIdentifier = "com.checkout.risk-mobile-sdk"
}
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ struct LoggerService: LoggerServiceProtocol {
switch internalConfig.environment {
case .qa, .sandbox:
logEnvironment = .sandbox
case .prod:
case .production:
logEnvironment = .production
}

Expand Down
12 changes: 12 additions & 0 deletions Sources/Risk/Models/PublishRiskData.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//
// PublishRiskData.swift
//
//
// Created by Precious Ossai on 30/10/2023.
//

import Foundation

public struct PublishRiskData {
public let deviceSessionId: String
}
13 changes: 13 additions & 0 deletions Sources/Risk/Models/RiskIntegrationType.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// RiskIntegrationType.swift
//
//
// Created by Precious Ossai on 20/02/2024.
//

import Foundation

enum RiskIntegrationType: String, Codable {
case standalone = "RiskIosStandalone"
case inFrames = "RiskIosInFramesIos"
}
39 changes: 39 additions & 0 deletions Sources/Risk/Models/RiskSDKInternalConfig.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//
// RiskSDKInternalConfig.swift
//
//
// Created by Precious Ossai on 20/02/2024.
//

import Foundation

struct RiskSDKInternalConfig {
let merchantPublicKey: String
let deviceDataEndpoint: String
let fingerprintEndpoint: String
let integrationType: RiskIntegrationType
let sourceType: SourceType
let framesMode: Bool
let environment: RiskEnvironment

init(config: RiskConfig) {
merchantPublicKey = config.publicKey
environment = config.environment
framesMode = config.framesMode
integrationType = framesMode ? .inFrames : .standalone
sourceType = framesMode ? .cardToken : .riskSDK

switch environment {
case .qa:
deviceDataEndpoint = "https://prism-qa.ckotech.co/collect"
fingerprintEndpoint = "https://fpjs.cko-qa.ckotech.co"
case .sandbox:
deviceDataEndpoint = "https://risk.sandbox.checkout.com/collect"
fingerprintEndpoint = "https://fpjs.sandbox.checkout.com"
case .production:
deviceDataEndpoint = "https://risk.checkout.com/collect"
fingerprintEndpoint = "https://fpjs.checkout.com"
}
}

}
13 changes: 13 additions & 0 deletions Sources/Risk/Models/SourceType.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// SourceType.swift
//
//
// Created by Precious Ossai on 20/02/2024.
//

import Foundation

enum SourceType: String {
case cardToken = "card_token"
case riskSDK = "riskios"
}
Loading

0 comments on commit 4823f05

Please sign in to comment.