# iOS SDK

> Install the fraud detection SDK in an iOS app with Swift Package Manager: capabilities, location permissions, sending transactions, and the changelog.

URL: https://docs.ironchip.com/en/fraude/sdk/ios/

The iOS SDK collects device and environment signals on every sensitive operation and sends them to the Ironchip fraud engine. Use it if your mobile app is a native iOS app.

## Requirements

| Platform | Supported versions |
| -------- | ------------------ |
| iOS      | 13.0.0+            |

## Installation

### Add the package with Xcode

1. In Xcode, go to the root of your application (for example, `ExampleApp.xcodeproj`), select the `ExampleApp` item under **PROJECT**, and open the third tab, **Package Dependencies**.
2. Click the **+** button.
3. In the pop-up window, paste the repository URL into the search field and click **Add Package**: [https://github.com/Ironchip-Security/LBFraud-SDK-iOS.git](https://github.com/Ironchip-Security/LBFraud-SDK-iOS.git)
4. Under **Dependency Rule**, choose an exact version, a range of versions, or a branch. Choose the exact version `1.2.10` (the latest release), or the **Up to Next Major Version** rule starting at `1.2.10`, which makes package upgrades easier.

   [Image: Xcode window for adding the LBFraud package with the dependency rule]

### Add the Wi-Fi capability

To use Ironchip LBFraud as a Swift Package, add a capability to your app target: go to **Signing & Capabilities** and add **Access WiFi Information**.

[Image: Xcode Signing & Capabilities tab with the Access WiFi Information capability]

### Add the location permissions

In the app target, open the **Info** tab and add the following keys. For each one, enter the description as a string:

1. `Privacy - Location Always and When In Use Usage Description`
2. `Privacy - Location When In Use Usage Description`
3. `Privacy - Location Always Usage Description`
4. `LSApplicationQueriesSchemes`: this permission lets the SDK detect whether the device is jailbroken.

[Image: Xcode Info tab with the location permission keys added]

### Request the location permission

Before using the SDK, your app must request the location permission:

```swift
import CoreLocation

let locationManager = CLLocationManager()
locationManager.requestWhenInUseAuthorization()
```

## Use in an app

Call the library initialization method on the main thread.

```swift
import LBFraudSDKiOS
...

// Replace apikey with the API key generated in the console.
let ironchipLBFraud = LBFraudSDK.init(apikey: "XXXXXX.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
// The SDK sends transactions to the Ironchip production environment.

// Send a transaction to the Ironchip fraud engine for analysis
let extraData: [String: Any] = [
    "concept": "Book august",
    "amount": 60,
    "operation": "booking"
]

// transactionId (required, unique): identifier you will later use to request the report
// userId (required): user identifier
// extraData (optional): extra information for analysis

// sendTransaction accepts two callbacks: the first runs when the transaction has finished
// and the second runs if an error occurs during the process.

ironchipLBFraud.sendTransaction(transactionId: "random_identifier_generated", userId: "john.doe@gmail.com", extraData: extraData, finish: {
    // Code to run when the transaction has finished.
    }, onError: { err in

    // Code to run if an error occurs during the transaction.

    // Example:
        //if(err is TransactionError) {

            // let transactionError = err as! TransactionError

            // print(transactionError.traceability_id)
            // print(transactionError.message)
            // print(transactionError.http_code)
            // print(transactionError.code)
        //} else {
            // print("NetworkError: ", err)
        //}
    }
)
```

## Example

Full example: after a successful login, the user identifier is anonymized with SHA-256 and the transaction is sent.

```swift
import LBFraudSDKiOS
import Foundation
import CommonCrypto

// Replace apikey with the API key generated in the console.
let ironchipLBFraud = LBFraudSDK.init(apikey: "XXXXXX.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")

// Log in and send the transaction if the login succeeds
func login(username: String, password: String) {
    Task {
        let loginSuccessful = await performLogin(username: username, password: password)

        if loginSuccessful {
            // If the login succeeds, call sendTransaction with the required parameters
            let transactionID = generateRandomTransactionID(length: 10) // Generate a unique transaction ID
            let anonymizedUserID = anonymizeUserID(username) // Anonymized user ID

            let extraData: [String: Any] = [
                "amount": 30, // Use an appropriate amount
                "operation": "login" // Specify the operation
            ]

            await sendTransactionAfterLogin(transactionID: transactionID, anonymizedUserID: anonymizedUserID, extraData: extraData)
        } else {
            // Handle the login failure
        }
    }
}

// Simulated asynchronous login
func performLogin(username: String, password: String) async -> Bool {
    try? await Task.sleep(nanoseconds: 2 * 1_000_000_000)

    return true
}

// Send the transaction after a successful login
func sendTransactionAfterLogin(transactionID: String, anonymizedUserID: String, extraData: [String: Any]) async {
    ironchipLBFraud.sendTransaction(transactionId: transactionID, userId: anonymizedUserID, extraData: extraData, finish: {
        // Code to run when the transaction has finished.
    }, onError: { err in
        // Code to run if an error occurs during the transaction.
    })
}

// Generate a transaction ID
func generateRandomTransactionID(length: Int) -> String {
    let characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
    var randomID = ""
    for _ in 0..<length {
        if let randomCharacter = characters.randomElement() {
            randomID.append(randomCharacter)
        }
    }
    return randomID
}

// Trim, lowercase, and hash the userId
func anonymizeUserID(_ userId: String) -> String {
    let trimmedLowercaseUserID = userId.trimmingCharacters(in: .whitespacesAndNewlines).lowercased()
    return sha256Hash(trimmedLowercaseUserID)
}

// Compute the hash with SHA-256
func sha256Hash(_ input: String) -> String {
    let inputData = Data(input.utf8)
    var hash = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
    inputData.withUnsafeBytes {
        _ = CC_SHA256($0.baseAddress, CC_LONG(inputData.count), &hash)
    }

    return hash.map { String(format: "%02x", $0) }.joined()
}
```

## Changelog

### 1.2.10 (2023-10-11)

**Added**

- Communication detection.
- SIM network type (2G, 3G, 4G, 5G).

### 1.2.9 (2023-05-18)

**Added**

- SDK version added to the transaction model.

### 1.2.8 (2023-05-12)

**Removed**

- Transaction model updated to remove information about the device's SIM and eSIM cards.

### 1.2.7 (2023-03-23)

**Added**

- Commons is now linked from LBFraud instead of being embedded.

### 1.2.6 (2023-03-15)

**Added**

- Transaction model updated to include information about the device's SIM and eSIM cards.

### 1.2.5 (2023-02-02)

**Changed**

- Transaction model updated to include the status of the requested permissions.
- Transaction model updated to include whether the GPS and Wi-Fi providers are enabled.

### 1.2.4 (2022-12-20)

**Changed**

- Fixed the problem when validating the app in the App Store.
- Location service logs for iOS 13.

### 1.2.3 (2022-12-09)

**Changed**

- Fixed an issue with the fingerprint ID.
- Handling of external HTTP calls.

### 1.2.2 (2022-11-30)

**Changed**

- Changed some device properties in the transaction model.

### 1.2.1 (2022-11-22)

**Changed**

- Class name refactoring.
- Log tags updated to match the refactoring.
- The Fraud constructor no longer accepts a URL host; it only allows selecting the desired environment.
- The GPS service throws an error when the permission is not granted or the location service is disabled.

### 1.2.0 (2022-10-31)

**Added**

- Debug logs.

**Changed**

- Changes in the transaction model.
- Management of new errors in the Commons library.

**Removed**

- Custom network errors: generic errors are now thrown instead.

### 1.1.8 (2022-10-25)

**Changed**

- Version 1.1.7 was promoted to 1.1.8 for organizational reasons.

### 1.1.7 (2022-10-25)

**Added**

- Support for iOS 13 and later.

**Changed**

- The package URL moved to GitHub.

### 1.1.6 (2022-09-14)

**Removed**

- Unnecessary `print` statements.

### 1.1.5 (2022-09-14)

**Added**

- The Commons library throws custom errors, and LBFraud rethrows them.

**Changed**

- Commons services renamed.

### 1.1.4 (2022-09-12)

**Added**

- `CHANGELOG` file added to the project.

**Changed**

- Model parameter names and structure changed.

### 1.1.2 (2022-09-03)

**Changed**

- Changed the repository name of the `.xcframework.zip`.

### 1.1.1 (2022-08-27)

**Added**

- The project now has two `.xcframework` files: one for the Commons library and one for LBFraud.

**Changed**

- The Swift Package now gets the `.xcframework` from a remote location instead of a local one.

### 1.1.0 (2022-08-24)

**Added**

- `LICENSE` file added to the project.

### 1.0.9 (2022-08-23)

**Added**

- First stable version of a Swift Package with one XCFramework called `LBFraudSDKiOS.xcframework`.
