Tích hợp Android
Yêu cầu
- Yêu cầu Android SDK >= 6.0 (API level 23).
Bước 1: Tải SDK và cấu hình Project
- Tải về bộ tích hợp SDK tại https://github.com/VNPT-SmartCA/vnpt_smartca_sdk_android/releases và giải nén ra thư mục.
- Sau khi giải nén, copy các file .aar và thư mục repo vào thư mục
android/app/libs
của project Android (nếu chưa có thư mụclibs
thì tạo mới)
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 (xem bước 1)
implementation files('libs/vnpt_smartca_sdk_lib-release-v1.0.aar')
implementation files('libs/ekyc_sdk-release-v3.2.7.aar')
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 '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'
}
//..
- 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:
- Kotlin
- Java
````kotlin
// ...
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
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)
//...
}
````````java
// ...
import com.google.gson.Gson
import com.vnpt.smartca.*
public class MainActivity extends AppCompatActivity {
//...
VNPTSmartCASDK mVNPTSmartCA = new VNPTSmartCASDK();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//...
CustomParams customParams = new CustomParams();
customParams.setCustomerId(""); // Số CCCD, giấy tờ của KH đăng nhập SDK, để trống KH tự nhập
customParams.setCustomerPhone(""); // Số ĐT của KH
customParams.setCustomerPassword(""); // Mật khẩu mặc định khi tạo tài khoản
customParams.setBorderRadiusBtn(999.0); // Border radius của button
customParams.setColorPrimaryBtn(""); // Màu background nút phụ ví dụ: #FFFFFF
customParams.setColorSecondBtn(""); // Màu background nút chính ví dụ: #4788FF
customParams.setPackageDefault(""); // Gói mặc định hiển thị khi mua Chứng thư số, ví dụ: PS0
customParams.setFeaturesLink(""); // Đường dẫn tới trang hướng dẫn sử dụng các tính năng sdk
customParams.setLogoCustom(""); // Logo của đối tác theo mã hoá Base64 dạng "iVBORw0KGgoAAAANSUhEUgAAANgAAA......"
customParams.setBackgroundLogin(""); // Background của đối tác theo mã hoá Base64 dạng "iVBORw0KGgoAAAANSUhEUgAAANgAAA......"
ConfigSDK config = new 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
customParams,
SmartCALanguage.INSTANCE.getVI(), // Ngôn ngữ vi/en
SmartCAEnvironment.INSTANCE.getDEMO_ENV(), // Môi trường kết nối DEMO/PROD
false // true nếu ứng dụng phát triển bằng Flutter, hoặc tích hợp Flutter module
);
mVNPTSmartCA.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,...
- Kotlin
- Java
```` kotlin
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;
}
}
````
````java
private void getMainInfo() {
try {
mVNPTSmartCA.getMainInfo(smartCAResult -> {
if (smartCAResult.getStatus() == SmartCAResultCode.INSTANCE.getSUCCESS_CODE()) {
// Xử lý khi confirm thành công
} else {
// Xử lý khi confirm thất bại
// smartCAResult.getStatusDesc
// smartCAResult.getData
}
return null;
});
} catch (Exception ex) {
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.
- 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"
- Kotlin
- Java
```` kotlin
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;
}
}
````
````java
private void getAuthentication() {
try {
mVNPTSmartCA.getAuthentication(smartCAResult -> {
if (smartCAResult.getStatus() == SmartCAResultCode.INSTANCE.getSUCCESS_CODE()) {
try {
CallbackResult obj;
String jsonString = smartCAResult.getData().toString();
Gson gson = new Gson();
obj = gson.fromJson(jsonString, CallbackResult.class);
String token = obj.getAccessToken();
String credentialId = obj.getCredentialId();
} catch (JsonParseException e) {
e.printStackTrace();
}
}
return null;
});
} catch (Exception ex) {
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
- Kotlin
- Java
```` kotlin
// 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;
}
}
````
````java
private void confirmTrans(String transId) {
if (transId.isEmpty()) {
editTextTran.setError("Vui lòng điền Id giao dịch");
return;
}
mVNPTSmartCA.getWaitingTransaction(transId,
smartCAResult -> {
if (smartCAResult.getStatus() == SmartCAResultCode.INSTANCE.getSUCCESS_CODE()) {
// Xử lý khi confirm thành công
} else {
// Xử lý khi confirm thất bại
// smartCAResult.getStatusDesc
// smartCAResult.getData
}
return null;
});
}
````
📦 Đăng xuất
- Đăng xuất tài khoản đang đăng nhập vào SDK.
- Kotlin
- Java
```` kotlin
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;
}
}
````
````java
private void singOut() {
try {
mVNPTSmartCA.signOut(smartCAResult -> {
if (smartCAResult.getStatus() == SmartCAResultCode.INSTANCE.getSUCCESS_CODE()) {
// Xử lý khi thành công
} else {
// Xử lý khi confirm thất bại
}
return null;
});
} catch (Exception ex) {
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.
- Kotlin
- Java
```` kotlin
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;
}
}
````````java
private void createAccount() {
try {
mVNPTSmartCA.createAccount(smartCAResult -> {
if (smartCAResult.getStatus() == SmartCAResultCode.INSTANCE.getSUCCESS_CODE()) {
// Xử lý khi thành công
} else {
// Xử lý khi thất bại
}
return null;
});
} catch (Exception ex) {
throw ex;
}
}
````
📦 Hàm hủy kết nối với SDK
- Kotlin
- Java
```` kotlin
override fun onDestroy() {
VNPTSmartCA.destroySDK()
super.onDestroy()
}
````
````java
@Override
protected void onDestroy() {
super.onDestroy();
mVNPTSmartCA.destroySDK();
}
````