Flow¶
GiniHealth
and PaymentComponent
are the main classes for interacting with the Gini Health SDK. GiniHealth
manages interaction with the Gini Health API and PaymentComponent
manages the data and state used by every
PaymentComponentView
and related screens.
The recommended flow is:
- Create the GiniHealth instance
- Upload documents
- Check which documents/invoices are payable
- Create the PaymentComponent instance
- Add a listener to the PaymentComponent
- Load payment providers
- Show the PaymentComponentViews
- Show the MoreInformationFragment
- Show the BankSelectionBottomSheet
- Show the ReviewFragment
Create the GiniHealth instance¶
Before creating an instance of GiniHealth
you need to create an instance of the GiniHealthAPI
. The Gini Health
SDK provides the following two helper methods for creating the GiniHealthAPI
instance:
getGiniApi(context: Context, clientId: String, clientSecret: String, emailDomain: String)
getGiniApi(context: Context, sessionManager: SessionManager)
After that you can create an instance of GiniHealth
:
val giniHealth = GiniHealth(giniHealthApi)
Upload documents¶
Uploading documents is achieved via the GiniHealthAPI
instance’s documentManager
. You can access it by using the
giniHealth.giniHealthAPI.documentManager
property.
For each document page a partial document needs to be created. The following example shows how to create a new partial document from a byte array containing a JPEG image:
// Assuming `imageBytes` is an instance of a byte array containing a JPEG image,
// e.g. from a picture taken by the camera
coroutineScope.launch {
// Create a partial document by uploading the document data
val partialDocumentResource =
giniHealth.giniHealthApi.documentManager.createPartialDocument(imageBytes, "image/jpeg", "document_page_1.jpg")
when (partialDocumentResource) {
is Resource.Success -> {
// Use the partial document
val partialDocument = partialDocumentResource.data
}
is Resource.Error -> // Handle error
is Resource.Cancelled -> // Handle cancellation
}
}
After all partial documents have been created you can create a composite document from the partials to bundle them into one final document:
// Assuming `partialDocuments` is a list of `Documents` which were
// returned by `createPartialDocument(...)` calls
coroutineScope.launch {
// Create a composite document by uploading the document data
val compositeDocumentResource =
giniHealth.giniHealthApi.documentManager.createCompositeDocument(partialDocuments)
when (compositeDocumentResource) {
is Resource.Success -> {
// Use the composite document
val compositeDocument = compositeDocumentResource.data
}
is Resource.Error -> // Handle error
is Resource.Cancelled -> // Handle cancellation
}
}
Check which documents/invoices are payable¶
Call giniHealth.checkIfDocumentIsPayable()
with the composite document id for each invoice to check whether it is
payable. We recommend performing this check only once right after the invoice has been uploaded and processed by Gini’s
Health API. You can then store the isPayable
state in your own data model.
// Assuming `compositeDocument` is `Document` returned by `createCompositeDocument(...)`
coroutineScope.launch {
try {
// Check whether the composite document is payable
val isPayable = giniHealth.checkIfDocumentIsPayable(compositeDocument.id)
} catch (e: Exception) {
// Handle error
}
}
Create the PaymentComponent instance¶
For creating an instance of the PaymentComponent
you need to pass in the Android context (either the application or
an activity context) and the GiniHealth
instance:
val paymentComponent = PaymentComponent(context, giniHealth)
Add a listener to the PaymentComponent¶
Set a listener on the PaymentComponent
to get informed of events from every PaymentComponentView
:
paymentComponent.listener = object: PaymentComponent.Listener {
override fun onMoreInformationClicked() {
// Show the MoreInformationFragment.
}
override fun onBankPickerClicked() {
// Show the BankSelectionBottomSheet.
}
override fun onPayInvoiceClicked(documentId: String) {
// Show the ReviewFragment.
}
}
Load payment providers¶
Call paymentComponent.loadPaymentProviderApps()
to load the available payment providers from the Gini Health API and
to check which ones are installed on the user’s device.
Note
It should be sufficient to call paymentComponent.loadPaymentProviderApps()
only once when your app starts.
Show the PaymentComponentViews¶
The PaymentComponentView
is a custom view widget and the main entry point for users. It allows them to pick a bank
and initiate the payment process. In addition, it also allows users to view more information about the payment feature.
The PaymentComponentView
is hidden by default and should be added to the layout of each invoice item:
<net.gini.android.health.sdk.paymentcomponent.PaymentComponentView
android:id="@+id/payment_component"
android:layout_width="match_parent"
android:layout_height="wrap_content"
... />
When creating the view holder for the invoice item, pass the PaymentComponent
instance to the view holder:
val paymentComponentView = view.findViewById(R.id.payment_component)
paymentComponentView.paymentComponent = paymentComponent
When binding the view holder of the invoice item, prepare it for reuse, set the payable state and the document id:
viewHolder.paymentComponentView.prepareForReuse()
viewHolder.paymentComponentView.isPayable = invoiceItem.isPayable
viewHolder.paymentComponentView.documentId = invoiceItem.documentId
Note
The PaymentComponentView
will only be visible if its isPayable
property is true
.
Show the MoreInformationFragment¶
The MoreInformationFragment
shows the Payment Feature Info Screen. It displays information and an FAQ section about the payment feature. It requires a
PaymentComponent
instance to show the icons of the available banks.
To instantiate it use MoreInformationFragment.newInstance()
and pass in your PaymentComponent
instance:
MoreInformationFragment.newInstance(paymentComponent)
Note
The MoreInformationFragment
doesn’t handle navigation related events and doesn’t show a navigation bar. You are
free to design navigation to and from the fragment as you see fit.
For the navigation bar title you should use the ghs_more_information_fragment_title
string resource.
Warning
You need to override the ghs_privacy_policy_link_url
string resource to provide a link to your company’s privacy
policy page. This link will be shown to users in the answer to the “Who or what is Gini?” question.
Show the BankSelectionBottomSheet¶
The BankSelectionBottomSheet
displays a list of available banks for the user to choose from. If a banking app is not
installed it will also display its Play Store link.
To instantiate it use BankSelectionBottomSheet.newInstance()
and pass in your PaymentComponent
instance:
BankSelectionBottomSheet.newInstance(paymentComponent)
Show the ReviewFragment¶
The ReviewFragment
displays an invoice’s pages and extractions. It also lets users pay the invoice with the bank
they selected in the BankSelectionBottomSheet
.
To instantiate it use paymentComponent.getPaymentReviewFragment()
and pass in the Gini Health API’s document id of
the invoice and the configuration for the screen. Also set a listener to get informed of events from the fragment:
val reviewConfiguration = ReviewConfiguration(...)
val paymentReviewFragment = paymentComponent.getPaymentReviewFragment(
documentId, reviewConfiguration
)
paymentReviewFragment.listener = object : ReviewFragmentListener {
override fun onCloseReview() {
// Called only when the ``ReviewConfiguration.showCloseButton`` was set to ``true``.
// Dismiss the ReviewFragment.
}
override fun onToTheBankButtonClicked(paymentProviderName: String) {
// Log or track the used payment provider name.
// No action required, the payment process is handled by the Gini Health SDK.
}
}
Note
paymentComponent.getPaymentReviewFragment()
will load the document extractions asynchronously. It’s a suspend
function and must be called from a coroutine.
The ReviewFragment
doesn’t handle navigation related events and doesn’t show a navigation bar. You are
free to design navigation to and from the fragment as you see fit.
The ReviewConfiguration
class contains the following options:
handleErrorsInternally
: If set totrue
, theReviewFragment
will handle errors internally and show snackbars for errors. If set tofalse
, errors will be ignored by theReviewFragment
. In this case the flows exposed byGiniHealth
should be observed for errors. Default value istrue
.showCloseButton
: If set totrue
, a floating close button will be shown in the top right corner of the screen. Default value isfalse
.