Tích hợp SDK Android Native
Thư viện TingeePaySDK (AAR) hỗ trợ tích hợp cổng thanh toán Tingee vào ứng dụng Android Native sử dụng ngôn ngữ Kotlin hoặc Java.
1. Cài đặt SDK
Thực hiện các bước sau để tích hợp tệp AAR vào ứng dụng của bạn:
- Tải về file thư viện: tingeepaysdk-release.aar.
- Sao chép tệp
tingeepaysdk-release.aarvừa tải vào thư mụcapp/libs/của dự án (tự tạo thư mụclibsnếu chưa tồn tại). - Mở tệp build cấu hình của ứng dụng (trong module
app) và thêm cấu hình dependencies tùy thuộc vào Gradle DSL bạn sử dụng:
- Kotlin DSL (build.gradle.kts)
- Groovy DSL (build.gradle)
dependencies {
// Tích hợp tệp AAR cục bộ
implementation(files("libs/tingeepaysdk-release.aar"))
// Các thư viện bắt buộc SDK phụ thuộc (nhập nếu chưa có)
implementation("androidx.appcompat:appcompat:1.3.0")
implementation("com.google.android.material:material:1.6.1")
implementation("androidx.constraintlayout:constraintlayout:2.0.0")
implementation("androidx.activity:activity:1.8.0")
}
dependencies {
// Tích hợp tệp AAR cục bộ
implementation files('libs/tingeepaysdk-release.aar')
// Các thư viện bắt buộc SDK phụ thuộc (nhập nếu chưa có)
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.6.1'
implementation 'androidx.constraintlayout:constraintlayout:2.0.0'
implementation 'androidx.activity:activity:1.8.0'
}
- Đồng bộ lại dự án của bạn bằng cách nhấn File → Sync Project with Gradle Files.
2. Khai báo quyền ứng dụng
SDK yêu cầu kết nối Internet để tải cổng thanh toán. Hãy chắc chắn rằng bạn đã định nghĩa quyền INTERNET trong tệp AndroidManifest.xml của ứng dụng:
<manifest xmlns:android="http://schemas.microsoft.com/apk/res/android"
package="your.package.name">
<!-- Thêm dòng này nếu chưa có -->
<uses-permission android:name="android.permission.INTERNET" />
<application ...>
...
</application>
</manifest>
3. Khởi động màn hình thanh toán
Cổng thanh toán cung cấp hai phương thức hiển thị chính: Toàn màn hình (FullScreen) hoặc Nửa màn hình (Bottom Sheet).
Trước khi mở SDK, bạn cần lấy paymentUrl từ hệ thống máy chủ (Backend) của bạn (qua API Tạo link thanh toán) và chuẩn bị returnUrl đã đăng ký.
3.1. Gọi từ Activity (Khuyên dùng)
Sử dụng ActivityResultLauncher để khởi động màn hình thanh toán và nhận kết quả trả về một cách hiện đại.
Bước 1: Đăng ký Launcher trong Activity của bạn
private val paymentResultLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result ->
if (result.resultCode == Activity.RESULT_OK) {
val data = result.data
val status = data?.getStringExtra("EXTRA_PAYMENT_STATUS")
val orderId = data?.getStringExtra("EXTRA_ORDER_ID")
val transactionCode = data?.getStringExtra("EXTRA_TRANSACTION_CODE")
val errorCode = data?.getStringExtra("EXTRA_ERROR_CODE")
val errorMessage = data?.getStringExtra("EXTRA_ERROR_MESSAGE")
val rawJson = data?.getStringExtra("EXTRA_PAYMENT_DATA_JSON")
when (status) {
"success" -> { /* Thanh toán thành công */ }
"failed" -> { /* Thanh toán thất bại */ }
"cancelled" -> { /* Người dùng đã hủy giao dịch trên cổng */ }
"expired" -> { /* Mã thanh toán hết hạn */ }
"error" -> { /* Lỗi hệ thống phát sinh */ }
}
} else {
// Người dùng đóng màn hình SDK (bằng cử chỉ vuốt, nút quay lại vật lý) mà không có kết quả
}
}
Bước 2: Mở cổng thanh toán khi có URL
val intent = TingeePaySDK.createIntent(
context = this,
paymentUrl = paymentUrl, // URL thanh toán lấy từ API Backend của bạn
returnUrl = returnUrl, // URL/Deep link trả về đã khai báo
isEmbedded = true, // true: Ẩn các phần header/footer không cần thiết của web (khuyên dùng)
immediateResult = true, // true: Bắn kết quả trả về ngay khi hoàn tất
primaryColor = "#1E88E5", // Màu sắc thương hiệu dạng Hex (null = sử dụng mặc định)
isFullScreen = true // true: Toàn màn hình | false: Hiển thị Bottom Sheet (nửa màn hình)
)
paymentResultLauncher.launch(intent)
3.2. Gọi từ Fragment
Khi mở SDK từ một Fragment, bạn cần lưu ý hai điểm quan trọng sau:
registerForActivityResultbắt buộc phải được khai báo dưới dạng thuộc tính (Property) ở cấp lớp của Fragment. Không được khai báo bên trong các hàm callback nhưonViewCreated(),onStart(), hoặc trong các sự kiện click listener (vi phạm sẽ gây lỗiIllegalStateExceptionkhi chạy ứng dụng).- Sử dụng hàm
requireContext()thay thế chothiskhi truyền tham số ngữ cảnh.
class CheckoutFragment : Fragment() {
// ✅ Khai báo Launcher như một Property ở cấp lớp
private val paymentResultLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result ->
if (result.resultCode == Activity.RESULT_OK) {
val status = result.data?.getStringExtra("EXTRA_PAYMENT_STATUS")
val orderId = result.data?.getStringExtra("EXTRA_ORDER_ID")
// Xử lý logic kết quả...
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
btnPay.setOnClickListener {
// ✅ Khởi tạo Intent và kích hoạt Launcher từ sự kiện click
val intent = TingeePaySDK.createIntent(
context = requireContext(), // Dùng requireContext()
paymentUrl = paymentUrl,
returnUrl = returnUrl,
isEmbedded = true,
immediateResult = true,
primaryColor = "#1E88E5",
isFullScreen = false // Ví dụ: mở dạng Bottom Sheet
)
paymentResultLauncher.launch(intent)
}
}
}
4. Mô tả các tham số cấu hình
Hàm TingeePaySDK.createIntent hỗ trợ các tham số cấu hình linh hoạt:
| Tham số | Kiểu dữ liệu | Mặc định | Mô tả |
|---|---|---|---|
context | Context | — | Ngữ cảnh của Activity/Fragment đang gọi. |
paymentUrl | String | — | Bắt buộc. Đường dẫn thanh toán được tạo từ API Backend. |
returnUrl | String? | null | URL hoặc deep link để chuyển hướng ứng dụng sau khi hoàn thành. |
isEmbedded | Boolean | true | Nếu đặt là true, SDK sẽ ẩn thanh header và footer mặc định của web cổng thanh toán để tạo cảm giác native. |
immediateResult | Boolean | true | true để gửi kết quả ngay lập tức khi hệ thống cổng thanh toán hoàn thành xử lý. |
primaryColor | String? | null | Màu sắc chủ đạo của giao diện thanh toán dạng chuỗi Hex (ví dụ: "#E53935"). Nếu null, hệ thống sử dụng màu mặc định của cổng. |
isFullScreen | Boolean | true | Cấu hình chế độ hiển thị: - true: Hiển thị toàn màn hình.- false: Hiển thị dạng Bottom Sheet (chiếm khoảng 50% chiều cao màn hình, hỗ trợ kéo xuống để đóng). |
5. Dữ liệu trả về từ SDK
Khi màn hình thanh toán kết thúc, SDK sẽ gọi hàm setResult(RESULT_OK, intent) và tự động đóng. Bạn có thể lấy các thông tin sau từ tệp Intent kết quả:
| Key định danh dữ liệu | Kiểu dữ liệu | Mô tả |
|---|---|---|
EXTRA_PAYMENT_STATUS | String | Trạng thái giao dịch trả về: success / failed / cancelled / expired / error |
EXTRA_ORDER_ID | String | Mã đơn hàng tương ứng trên hệ thống của bạn. |
EXTRA_TRANSACTION_CODE | String | Mã giao dịch được ghi nhận trên hệ thống cổng thanh toán Tingee. |
EXTRA_ERROR_CODE | String | Mã lỗi chi tiết (nếu có lỗi xảy ra). |
EXTRA_ERROR_MESSAGE | String | Nội dung thông báo lỗi chi tiết (nếu có lỗi xảy ra). |
EXTRA_PAYMENT_DATA_JSON | String | Toàn bộ thông tin cấu trúc JSON payload gốc từ cổng thanh toán. |
[!NOTE] Nếu người dùng chủ động đóng màn hình SDK (như vuốt đóng Bottom Sheet) trước khi có trạng thái cuối cùng,
resultCodetrả về sẽ làRESULT_CANCELED(0) và không chứa bất kỳ dữ liệu bổ sung nào trong Intent.
6. Yêu cầu hệ thống tối thiểu
| Danh mục | Yêu cầu |
|---|---|
| Android SDK tối thiểu | API 24 (Android 7.0 trở lên) |
| Target SDK | API 36 |
| Tương thích Java | Java 11 |
| Quyền mạng | Bắt buộc quyền sử dụng INTERNET |
| Ngôn ngữ phát triển | Kotlin hoặc Java |
7. Các lưu ý quan trọng khi tích hợp
- Quy trình tạo link: SDK di động không trực tiếp xử lý việc gọi API tạo đường dẫn thanh toán. Ứng dụng tích hợp có nhiệm vụ gọi về Backend của mình để nhận
paymentUrltrước khi chuyển tiếp cho SDK. - Tự động Deeplink: Khi người dùng chọn hình thức thanh toán bằng ứng dụng ngân hàng, SDK sẽ tự động phát hiện và mở ứng dụng ngân hàng tương thích đã cài trên thiết bị. Trong trường hợp thiết bị chưa cài đặt ứng dụng ngân hàng đó, SDK sẽ hiển thị thông báo popup thân thiện để người dùng thử lại hoặc chọn cách thanh toán khác.
- Bộ nhớ: SDK tự động giải phóng tài nguyên và dọn dẹp bộ nhớ đệm WebView khi đóng màn hình thanh toán để tránh gây rò rỉ bộ nhớ (memory leak).