Nhảy tới nội dung

Tích hợp Android

Yêu cầu
  • Yêu cầu Android >= 6.0 (API level 23).

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

Lưu ý

Ứng dụng viết bằng Flutter hoặc tích hợp Flutter module không copy thư mục repo

  • Thêm thông tin cấu hình vào file settings.gradle như dưới:
pluginManagement {  
repositories {
gradlePluginPortal()
google()
mavenCentral()
}
}

// Bỏ qua nếu ứng dụng viết bằng Flutter hoặc tích hợp Flutter module
String storageUrl = System.env.FLUTTER_STORAGE_BASE_URL ?: "https://storage.googleapis.com"

dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
jcenter()
maven { url "https://jitpack.io" }

// Bỏ qua nếu ứng dụng viết bằng Flutter hoặc tích hợp Flutter module
maven {
//Đường dẫn thư mục chứa **repo** ở bước 1
url 'app/libs/repo'
}
// Bỏ qua nếu ứng dụng viết bằng Flutter hoặc tích hợp Flutter module
maven {
url "$storageUrl/download.flutter.io"
}

}
}
  • Thêm các thông tin cấu hình vào app/build.gradle
//...
aaptOptions {
noCompress "bic"
}

dependencies {
//...
// Bỏ qua nếu ứng dụng viết bằng Flutter hoặc tích hợp Flutter module
implementation 'com.vnpt.smartca.module.vnpt_smartca_module:flutter_release:1.0'

// Đường dẫn tới các file aar
implementation files('libs/sdk_vnpt_smartca_library-release.aar')

implementation files('libs/ekyc_sdk-release-v3.5.3.aar')
implementation files('libs/scanqr_ic_sdk-release-v1.0.5.aar')

// eContract
implementation files('libs/eContract-v3.6.12.aar')
implementation 'com.auth0.android:jwtdecode:2.0.0'

implementation 'com.github.gcacace:signature-pad:1.3.1'
implementation "androidx.multidex:multidex:2.0.1"
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'

implementation 'androidx.test.espresso:espresso-idling-resource:3.5.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'com.github.mhiew:android-pdf-viewer:3.2.0-beta.3'

implementation 'com.squareup.okhttp3:okhttp:4.9.0'
implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0'
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.9.0'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.0.0'
implementation 'com.karumi:dexter:6.0.0'

implementation 'com.android.support:exifinterface:28.0.0'
implementation 'com.google.code.gson:gson:2.10'

implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
implementation 'io.reactivex.rxjava2:rxjava:2.2.12'
//end

// eKYC
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:design:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:2.0.4'
implementation 'de.hdodenhof:circleimageview:3.1.0'
implementation 'com.intuit.sdp:sdp-android:1.0.6'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation('me.dm7.barcodescanner:zxing:1.9.8')
implementation 'com.airbnb.android:lottie:5.0.1'
}

//..
  • Thêm FlutterActivity trong file AndroidManifest.xml như sau:
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
//......
<application
//......

// Bỏ qua nếu app tích hợp viết bằng Flutter
<activity android:name="io.flutter.embedding.android.FlutterFragmentActivity"
android:theme="@style/Theme.Smartca_android_example"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize"/>

</application>
  • Bổ sung thuộc tính dưới đây vào file gradle.properties
    android.enableJetifier=true
  • Bổ sung thuộc tính dưới đây vào file proguard-rules.pro
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontwarn android.support.**
-dontwarn com.squareup.**
-dontwarn com.google.android.**
-verbose

# -keepattributes *Annotation*
-dontwarn lombok.**
-dontwarn io.realm.**

-dontwarn java.awt.**

# okhttp3
-dontwarn okhttp3.**
-dontwarn okio.**
-dontwarn javax.annotation.**
-dontwarn org.conscrypt.**
# A resource is loaded with a relative path so the package of this class must be preserved.
-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase

# Application classes that will be serialized/deserialized over Gson
-keep class vnpt.it3.econtract.data.model.** { *; }
-keep class vnpt.it3.econtract.data.** { *; }

# Java 8
-dontwarn java.lang.invoke.*
-dontwarn **$$Lambda$*

# Retrofit 2
-dontnote retrofit2.Platform
-dontnote retrofit2.Platform$IOS$MainThreadExecutor
-dontwarn retrofit2.Platform$Java8
-keepattributes Signature
-keepattributes Exceptions
-keepclassmembernames,allowobfuscation interface * {
@retrofit2.http.* <methods>;
}
-keepclasseswithmembers class * {
@retrofit2.http.* <methods>;
}
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement


# pdf lib
-keep class com.shockwave.**

#To remove debug logs:
-assumenosideeffects class android.util.Log {
public static *** d(...);
public static *** v(...);
public static *** w(...);
public static *** i(...);
}

-keep public enum vnpt.it3.econtract.data.**{
*;
}

-keepclassmembers class **.R$* {
public static <fields>;
}
# Glide
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public class * extends com.bumptech.glide.module.AppGlideModule
-keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
**[] $VALUES;
public *;
}

-keep enum org.greenrobot.eventbus.ThreadMode { *; }
-keep class com.vnptit.innovation.sample.model.** { *; }
-keep class ai.icenter.face3d.native_lib.Face3DConfig { *; }
-keep class ai.icenter.face3d.native_lib.CardConfig { *; }

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

  • Thêm code kết nối với SDK tại Activity muốn sử dụng các chức năng:
    // ...
import com.google.gson.Gson
import com.vnpt.smartca.*

class MainActivity: AppCompatActivity() {
//...
var VNPTSmartCA = VNPTSmartCASDK()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

//...
var customParams = CustomParams(
customerId = "", // Số CCCD, giấy tờ của KH đăng nhập SDK, để trống KH tự nhập
borderRadiusBtn = 999.0, // Border radius của button
colorSecondBtn = "", // Màu background nút phụ ví dụ: #FFFFFF
colorPrimaryBtn = "", // Màu background nút chính ví dụ: #4788FF
featuresLink = "", // Đường dẫn tới trang hướng dẫn sử dụng các tính năng sdk
customerPhone = "", // Số ĐT mặc định của KH
customerEmail = "", // Email mặc định của KH
packageDefault = "", // Gói mặc định hiển thị khi mua Chứng thư số, ví dụ: PS0
password = "", // Mật khẩu mặc định khi tạo tài khoản
logoCustom = "", // Logo của đối tác theo mã hoá Base64 dạng "iVBORw0KGgoAAAANSUhEUgAAANgAAA......"
backgroundLogin = "" // Background của đối tác theo mã hoá Base64 dạng "iVBORw0KGgoAAAANSUhEUgAAANgAAA......"
);

var config = ConfigSDK(
clientId = "", // clientId tương ứng với môi trường được cấp qua email
clientSecret = "", // clientSecret tương ứng với môi trường được cấp qua email
env = SmartCAEnvironment.DEMO_ENV, // Môi trường kết nối DEMO/PROD
customParams = customParams,
lang = SmartCALanguage.VI, // Ngôn ngữ vi/en
isFlutter = true, // true nếu ứng dụng phát triển bằng Flutter, hoặc tích hợp Flutter module
)

VNPTSmartCA.initSDK(this, config)
//...

}

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

  • Quản lý tài khoản: Đăng ký tài khoản, Quản lý chứng thư, Lịch sử giao dịch, Tài khoản,...
  • Lấy thông tin xác thực người dùng (accessToken & credentiald & serial)
  • Xác nhận / Hủy giao dịch ký số
  • Tạo tài khoản
  • Đăng xuất
  • Hủy kết nối SDK

📦 Hàm quản lý tài khoản

  • Đối tác tạo 1 chức năng riêng trên ứng dụng của mình để người dùng sử dụng các chức năng của SDK như: Đăng ký tài khoản, Quản lý chứng thư, Lịch sử giao dịch, Tài khoản,...
private fun getMainInfo() {
try {
VNPTSmartCA.getMainInfo { result ->
when (result.status) {
SmartCAResultCode.SUCCESS_CODE -> {
// Xử lý khi thành công
}
else -> {
// Xử lý khi có lỗi
// result.statusDesc
// result.data
}
}
}
} catch (ex: java.lang.Exception) {
throw ex;
}
}

📦 Lấy thông tin người dùng, chứng thư số

  • Lấy accessToken, credentialId hoặc serial của chứng thư để tạo giao dịch phía backend. SDK sẽ tự kiểm tra tài khoản như: đã kích hoạt hay chưa, chứng thư hợp lệ hay không, tự động làm mới token khi hết hạn,...
  • Sau khi lấy được thông tin đối tác tạo giao dịch từ phía backend của mình với hệ thống backend VNPT SmartCA để lấy tranId sau đó gọi hàm getWaitingTransaction.
  • Đối tác tự bắn Notifycation về ứng dụng của mình để thông báo cho người dùng sau khi tạo giao dịch phía backend thành công, SDK VNPT SmartCA sẽ không bắn.
  • Tài liệu tích hợp phía backend được cung cấp khi đăng ký tích hợp.
Lưu ý

tranId là mã giao dịch do hệ thống VNPT SmartCA sinh ra và trả về cho đối tác. Ví dụ trandId: "48b7d184-bbf4-4fa2-a661-3a223dcb716a"


data class CallbackResult(
val credentialId: String,
val accessToken: String,
val serial: String,
)

private fun getAuthentication() {
try {
VNPTSmartCA.getAuthentication { result ->
when (result.status) {
SmartCAResultCode.SUCCESS_CODE -> {
val obj: CallbackResult = Gson().fromJson(
result.data.toString(), CallbackResult::class.java
)
// SDK trả lại token, credential, serial của khách hàng
// Đối tác tạo transaction cho khách hàng để lấy transId, sau đó gọi getWaitingTransaction
val token = obj.accessToken
val credentialId = obj.credentialId
val serial = obj.serial
//...
}
else -> {
// Xử lý lỗi
// result.statusDesc
// result.data
}
}
}
} catch (ex: Exception) {
throw ex;
}
}

📦 Xác nhận / Huỷ giao dịch ký số

  • Sau khi lấy lấy được tranId từ phía backend đối tác gọi hàm này để người dùng Xác nhận / Huỷ giao dịch ký số.
  • Luôn phải gọi hàm getAuthentication trước
// tạo giao dịch từ backend, lấy tranId từ hệ thống VNPT SmartCA trả về
private fun getWaitingTransaction(transId: String) {
try {
if (transId.isNullOrEmpty()) {
editTextTrans.setError("Vui lòng điền Id giao dịch");
return
}

VNPTSmartCA.getWaitingTransaction(transId) { result ->
when (result.status) {
SmartCAResultCode.SUCCESS_CODE -> {
// Xử lý khi thành công
}
else -> {
// Xử lý khi thất bại
// result.statusDesc
// result.data
}
}

}
} catch (ex: Exception) {
throw ex;
}
}

📦 Đăng xuất

  • Đăng xuất tài khoản đang đăng nhập vào SDK.
private fun signOut() {
try {
VNPTSmartCA.signOut { result ->
when (result.status) {
SmartCAResultCode.SUCCESS_CODE -> {
// Xử lý khi thành công
}
else -> {
// Xử lý khi lỗi
// result.statusDesc
// result.data
}
}
}
} catch (ex: java.lang.Exception) {
throw ex;
}
}

📦 Tạo tài khoản/Kích hoạt tài khoản

  • Mở trực tiếp màn hình tới màn hình tạo tài khoản.
private fun createAccount() {
try {
VNPTSmartCA.createAccount { result ->
when (result.status) {
SmartCAResultCode.SUCCESS_CODE -> {
// Xử lý khi thành công
}
else -> {
// Xử lý khi thất bại
// result.statusDesc
// result.data
}
}
}
} catch (ex: java.lang.Exception) {
throw ex;
}
}

📦 Hàm hủy kết nối với SDK

override fun onDestroy() {
VNPTSmartCA.destroySDK()
super.onDestroy()
}