Nhảy tới nội dung

Tích hợp iOS

Ghi chú

EContractSDK Native iOS là SDK cho phép tích hợp mô-đun Flutter eContract vào ứng dụng iOS native một cách dễ dàng. SDK cung cấp các phương thức tương tự như EContractInterface trong Flutter SDK để khách hàng có thể tương tác với Flutter module từ native iOS.

Yêu cầu
  • iOS 13.0 trở lên
  • Xcode 15.0 trở lên
  • Swift 5.9 trở lên

Bước 1: Tải SDK và cấu hình Project

  • 1.1. Tải SDK

Tải file EContractSDK.xcframework và các Flutter frameworks từ bản phát hành

  • 1.2. Thêm Framework vào Xcode Project

    Mở Xcode project của bạn

    Chọn target của ứng dụng

    Vào tab GeneralFrameworks, Libraries, and Embedded Content

    Click + và chọn Add Other...Add Files...

    Chọn các framework sau:

    • EContractSDK.xcframework

    • EContractApp.framework

    • EContractFlutter.framework

    • FlutterPluginRegistrant.xcframework (nếu có)

Đảm bảo tất cả frameworks được set là Embed & Sign

  • 1.3. Cấu hình Build Settings

Vào tab Build Settings

Tìm Framework Search Paths và thêm:

$(PROJECT_DIR)/path/to/Flutter/Release-iphoneos

$(PROJECT_DIR)/path/to/Flutter/Release-iphonesimulator

Tìm Other Linker Flags và thêm:

-framework Flutter

-framework App

  • 1.4. Cấu hình Info.plist

Thêm quyền cần thiết vào Info.plist (nếu chưa có):

    <key>NSPhotoLibraryUsageDescription</key> 
<string>Cần truy cập thư viện ảnh để chọn tài liệu</string>
<key>NSCameraUsageDescription</key>
<string>Cần truy cập camera để chụp ảnh tài liệu</string>

Bước 2: Khởi tạo SDK tại nơi bắt đầu kết nối

  • 2.1. Import Framework

Thêm import vào file Swift nơi bạn muốn sử dụng SDK:

importEContractSDK 
  • 2.2. Khởi tạo SDK trong AppDelegate hoặc SceneDelegate

Khởi tạo SDK một lần khi ứng dụng khởi động, tốt nhất là trong application(_:didFinishLaunchingWithOptions:) hoặc scene(_:willConnectTo:options:):

importUIKit 
importEContractSDK

@main

classAppDelegate:UIResponder,UIApplicationDelegate{
    funcapplication(_ application:UIApplication,

                     didFinishLaunchingWithOptions launchOptions:[UIApplication.LaunchOptionsKey:Any]?)->Bool{
        // Khởi tạo SDK với cấu hình

        let config:[String:Any]=[

            "token":"your_access_token",

            "clientId":"your_client_id",

            "clientSecret":"your_client_secret",

            "khachHangId":12345,

            "locale":"vi",  // hoặc "en"

            "env":"PROD"    // hoặc "DEV", "STAG"

        ]

        EContractSDK.initialize(config: config)

        returntrue

    }

}

Hoặc trong SceneDelegate (iOS 13+):

importUIKit 

importEContractSDK
classSceneDelegate:UIResponder,UIWindowSceneDelegate{

    funcscene(_ scene:UIScene,

               willConnectTo session:UISceneSession,

               options connectionOptions:UIScene.ConnectionOptions){

        // Khởi tạo SDK

        let config:[String:Any]=[

            "token":"your_access_token",

            "clientId":"your_client_id",

            "clientSecret":"your_client_secret",

            "khachHangId":12345,

            "locale":"vi",

            "env":"PROD"

        ]
        EContractSDK.initialize(config: config)
        // ... rest of your code

    }

}
  • 2.3. Tham số cấu hình
Tham sốKiểuBắt buộcMô tả
tokenStringAccess token để xác thực
clientIdStringClient ID của ứng dụng
clientSecretStringClient Secret của ứng dụng
khachHangIdIntID khách hàng
localeStringKhôngNgôn ngữ: "vi" hoặc "en" (mặc định: "vi")
envStringKhôngMôi trường: "STAG" hoặc "PROD" (mặc định: "PROD")

Bước 3: Sử dụng các hàm chính

  • 3.1. Launch SDK (Màn hình mặc định)
  • Mở SDK với màn hình mặc định:
importEContractSDK 
classViewController:UIViewController{

    @IBActionfunclaunchSDK(_ sender:UIButton){

        EContractSDK.launch(from:self){ result in

            self.handleResult(result)
        }

    }

    privatefunchandleResult(_ result:EContractSDKResult){

        switch result {

        case.success(let data):

            print("Success: \(data)")

        case.failure(let error):

            print("Error: \(error)")

        }

    }

}
  • 3.2. Điều hướng đến danh sách hợp đồng đến
EContractSDK.navigateToIncomingContracts(from:self){ result in 

    switch result {

    case.success(let data):

        // Xử lý kết quả thành công

        print("Hợp đồng đến: \(data)")

    case.failure(let error):

        // Xử lý lỗi

        print("Lỗi: \(error)")

    }

}
  • 3.3. Điều hướng đến danh sách hợp đồng đi
EContractSDK.navigateToOutgoingContracts(from:self){ result in 

    switch result {

    case.success(let data):

        print("Hợp đồng đi: \(data)")

    case.failure(let error):

        print("Lỗi: \(error)")

    }

}
  • 3.4. Điều hướng đến chi tiết hợp đồng
// Với contractId 

EContractSDK.navigateToContractScreen(

    from:self,

    contractId:"contract_123",

    documentFileId:nil,

    isLoginNoAccount:nil

){ result in

    switch result {

    case.success(let data):

        print("Chi tiết hợp đồng: \(data)")

    case.failure(let error):

        print("Lỗi: \(error)")

    }

}
// Với contractId và documentFileId 

EContractSDK.navigateToContractScreen(

    from:self,

    contractId:"contract_123",

    documentFileId:"doc_456",

    isLoginNoAccount:"false"

){ result in

    // Xử lý kết quả

}
  • 3.5. Điều hướng đến màn hình ký hợp đồng
// Ký hợp đồng (không có documentFileId - ký toàn bộ hợp đồng) 

EContractSDK.navigateToSignContract(

    from:self,

    contractId:"contract_123",

    documentFileId:nil,

    isLoginNoAccount:"false"

){ result in

    switch result {

    case.success(let data):

        print("Ký hợp đồng thành công: \(data)")

    case.failure(let error):

        print("Lỗi ký hợp đồng: \(error)")

    }

}
// Ký file cụ thể trong hợp đồng 

EContractSDK.navigateToSignContract(

    from:self,

    contractId:"contract_123",

    documentFileId:"doc_456",

    isLoginNoAccount:"false"

){ result in

    // Xử lý kết quả

}
  • 3.6. Điều hướng đến thông tin chữ ký
EContractSDK.navigateToSignatureInfo( 

    from:self,

    contractId:"contract_123",

    documentFileId:"doc_456",

    isLoginNoAccount:nil

){ result in

    switch result {

    case.success(let data):

        print("Thông tin chữ ký: \(data)")

    case.failure(let error):

        print("Lỗi: \(error)")

    }

}

📦 Tất cả các phương thức đều trả về EContractSDKResult:

publicenumEContractSDKResult{ 

    casesuccess([String:Any])  // Thành công, kèm dữ liệu

    casefailure(EContractSDKError)  // Lỗi

}



publicenumEContractSDKError:Error{

    case invalidHost      // Host không hợp lệ

    case flutterNotReady // Flutter chưa sẵn sàng

    case cancelled       // Người dùng hủy

    casemessage(String)// Lỗi với thông báo

}

Ví dụ xử lý:

EContractSDK.launch(from:self){ result in 

    switch result {

    case.success(let data):

        // Xử lý dữ liệu trả về

        iflet contractId = data["contractId"]as?String{

            print("Contract ID: \(contractId)")

        }

    case.failure(let error):

        switch error {

        case.cancelled:

            print("Người dùng đã hủy")

        case.flutterNotReady:

            print("Flutter chưa sẵn sàng, vui lòng thử lại")

        case.invalidHost:

            print("Host không hợp lệ")

        case.message(let msg):

            print("Lỗi: \(msg)")

        }

    }

}

Ví dụ hoàn chỉnh

importUIKit 

importEContractSDK
classViewController:UIViewController{
    overridefuncviewDidLoad(){

        super.viewDidLoad()

        setupUI()

    }

    privatefuncsetupUI(){

        // Tạo các button để test các chức năng

        let launchButton =UIButton(type:.system)

        launchButton.setTitle("Launch SDK",for:.normal)

        launchButton.addTarget(self, action:#selector(launchSDK),for:.touchUpInside)
        // ... thêm các button khác

    }

    

    @objcprivatefunclaunchSDK(){

        EContractSDK.launch(from:self){[weakself] result in

            self?.handleResult(result)
        }

    }

    

    privatefunchandleResult(_ result:EContractSDKResult){

        let alert:UIAlertController

        switch result {

        case.success(let data):

            alert =UIAlertController(

                title:"Thành công",

                message:"Dữ liệu: \(data)",

                preferredStyle:.alert

            )

        case.failure(let error):

            alert =UIAlertController(

                title:"Lỗi",

                message:"\(error)",

                preferredStyle:.alert

            )

        }

        alert.addAction(UIAlertAction(title:"OK", style:.default))

        present(alert, animated:true)

    }

}
Lưu ý

Lỗi: "Framework not found EContractSDK"

Giải pháp:

  1. Kiểm tra Framework Search Paths trong Build Settings

  2. Đảm bảo framework đã được thêm vào "Embed & Sign"

  3. Clean build folder (Shift + Cmd + K) và build lại

Lỗi

"Flutter not ready"

Giải pháp:

  1. Đảm bảo đã gọi EContractSDK.initialize(config:) trước khi sử dụng

  2. Kiểm tra các Flutter frameworks đã được embed đúng chưa

Lỗi: "dyld: Library not loaded"

Giải pháp:

  1. Kiểm tra tất cả frameworks đã được set "Embed & Sign"

  2. Kiểm tra Framework Search Paths

  3. Thử clean và rebuild project

Changelog

Version 1.0.0

  • Initial release

  • Hỗ trợ các chức năng cơ bản: launch, navigate to contract lists, contract detail, sign contract, signature info