diff --git a/CHANGELOG.md b/CHANGELOG.md index 9253745..f05c17c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,17 +1,16 @@ # Changelog -## v2.2.0 - May 15th, 2025 +## v2.3.0 - August 25th, 2025 ### Added -- GeoLocation support implemented -- Verify Retry support -- Rate Limiting support -- New UI screens and various UI improvements +- Localization support through PingOne +- Strengthened security for document uploads +- Support for Aadhaar Verification +- Improvements to support backend driven flows +- Support for selfie authentication mode ### Fixed -- Error handling -- UI defects -- AppTheme issues -- Other minor bugs +- Minor changes to improve UI/UX +- Defects related to verification flows diff --git a/README.md b/README.md index 324ca9f..bb1cd5e 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,105 @@ -# IDV_SDK_android -Prerequisites -- Android SDK 26 and up +# PingOne Verify SDK for Android +PingOneVerify Android SDK provides a secure interface for an Android app to use the PingOne Verify service for validating a user's identity. The SDK also parses the responses received from the service for different operations and forwards the same to the app via callbacks. -## Initializing PingOneVerifyClient -Implement the `DocumentSubmissionListener` interface and its functions +### Running the Sample App + + +[Download the Sample App](https://github.com/pingidentity/pingone-verify-mobile-sdk-android). + + +### Prerequisites +* Android Studio with Gradle +* Android SDK 26 and up + +### Set Up and Clone or Download + +The sample app can be run on a simulator but requires special set up and works much better on a device, because the app requires the camera to capture a selfie and and the related user ID documents. If you want to run the app on emulator you will need to use your PC's camera. + +1. Clone or download the [PingOne Verify SDK for Android](https://github.com/pingidentity/pingone-verify-mobile-sdk-android) sample code to your computer. The Sample Code directory contains the Android project that is ready to be built when the prerequisites are satisfied. + + +2. To open the sample app as a project in Android Studio, go to File --> New --> Import Project. Choose the SampleCode/PingOneVerify folder as the project's root folder. + +### Integrating PingOne Verify SDK with Your App + +PingOneVerify Android SDK provides a secure interface for an Android app to use the PingOne Verify service for validating a user's identity. The SDK also parses the responses received from the service for different operations and forwards the same to the app via callbacks. + +### Getting started +Add the dependencies needed for your application. + +If you haven't done so already, clone or download the [PingOne Verify SDK for Android](https://github.com/pingidentity/pingone-verify-mobile-sdk-android) sample app. You'll find the `.aar` dependencies required for the PingOne Verify Android SDK in the SDK directory. + +1. Create a `libs` folder, if it doesn't exist under your module, and copy the downloaded `.aar` dependencies: + + * PingOneVerify-2.3.0.aar + + * id_scanner_sdk.aar + + * voice_sdk.aar + + * iad.aar + +2. Add the following to your module level `build.gradle` file to include the dependencies in your module: + +``` +dependencies { + implementation fileTree(include: ["*.aar"], dir: "libs") + ... +} +``` +3. Because these components are loaded locally, you must also include the SDK's dependencies in the configuration to compile and run it. +``` +dependencies { + + implementation 'androidx.activity:activity-ktx:1.7.0' + implementation 'androidx.fragment:fragment-ktx:1.5.6' + implementation 'androidx.annotation:annotation:1.6.0' + implementation 'androidx.appcompat:appcompat:1.6.1' + implementation 'androidx.camera:camera-camera2:1.2.3' + implementation 'androidx.camera:camera-core:1.2.3' + implementation 'androidx.camera:camera-extensions:1.2.3' + implementation 'androidx.camera:camera-lifecycle:1.2.3' + implementation 'androidx.camera:camera-view:1.2.3' + implementation 'androidx.core:core-ktx:1.10.0' + implementation 'androidx.fragment:fragment-ktx:1.5.7' + + implementation 'com.google.android.material:material:1.9.0' + implementation 'com.google.code.gson:gson:2.9.0' + implementation 'com.googlecode.libphonenumber:libphonenumber:8.13.7' + + implementation 'com.google.android.gms:play-services-location:21.3.0' + implementation 'com.google.android.gms:play-services-mlkit-barcode-scanning:18.2.0' + implementation 'com.google.android.gms:play-services-mlkit-face-detection:17.1.0' + + implementation 'com.squareup.moshi:moshi:1.14.0' + implementation 'com.squareup.moshi:moshi-kotlin:1.14.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.3' + implementation 'com.squareup.okhttp3:okhttp-urlconnection:4.9.3' + implementation 'com.squareup.retrofit2:converter-moshi:2.9.0' + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.github.bumptech.glide:glide:4.16.0' + kapt 'com.github.bumptech.glide:compiler:4.16.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4' + implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.10' + + [//]: <> (IMPORTANT: Below dependencies must be defined for Selfie/Government ID document upload on S3) + implementation 'org.bitbucket.b_c:jose4j:0.9.5' + [//]: <> (IMPORTANT: Below dependencies should be defined for Selfie Liveness feature) + implementation 'com.google.protobuf:protobuf-javalite:3.20.1' + implementation 'com.google.protobuf:protobuf-kotlin-lite:3.20.1' + + } +``` + +### Initializing PingOneVerifyClient + +1. Import `com.pingidentity.sdk.pingoneverify.PingOneVerifyClient` in your desired Activity or Fragment +``` +import com.pingidentity.sdk.pingoneverify.PingOneVerifyClient; +``` +2. Implement the [DocumentSubmissionListener](#documentsubmissionlistener_callbacks) interface and its functions ````java public class CallingFragment extends Fragment implements DocumentSubmissionListener { // Callback when document is successfully submitted @@ -17,8 +111,8 @@ Implement the `DocumentSubmissionListener` interface and its functions } ```` -Instantiate a PingOneVerifyClient.Builder and set its listener and Activity -Start the Verification Process +3. Instantiate a PingOneVerifyClient.Builder and set its `listener` and `rootActivity` + Start the Verification Process ````java PingOneVerifyClient.Builder builder = new PingOneVerifyClient.Builder(false) .setRootActivity(getActivity()) @@ -29,6 +123,224 @@ Start the Verification Process }); ```` +4. Optionally, you can set an explicit **qrString** using the `PingOneVerifyClient.Builder` +````java + new PingOneVerifyClient.Builder(false) + .setListener(this) + .setRootActivity(getActivity()) + .setQrString(qrString: "https://api.pingone.com...") +```` + +5. Optionally, you can set a [Selfie Capture Settings](#selfiecapturesettings) with your preference using the `PingOneVerifyClient.Builder.` +````java +// Default is 45 seconds for captureTime and true for shouldCaptureAfterTimeout +SelfieCaptureSettings selfieCaptureSettings = new SelfieCaptureSettings(15, false) +List settings = new ArrayList<>(); +settings.add(selfieCaptureSettings); + +new PingOneVerifyClient.Builder(false) + .setRootActivity(getActivity()) + .setListener(this) + .setDocumentCaptureSettings(settings); +```` + +### DocumentSubmissionListener Callbacks + +1. `onDocumentSubmitted(DocumentSubmissionResponse response)` + + + * Called whenever a document is successfully submitted. + * Appropriate [DocumentSubmissionResponse](#documentsubmissionresponse) is returned +````java +public void onDocumentSubmitted(DocumentSubmissionResponse response) { + Log.d("The document status is :", response.getDocumentStatus()) + Log.d("The document submission status is", response.getDocumentSubmissionStatus()) + Map documents = response.getDocument(); + documents.forEach((k,v)->Log.d("(Key, Value):", "("+ k + ","+ v +")")); +} + +```` + +2. `onSubmissionComplete(DocumentSubmissionStatus status)` + + + * Called when all required documents have been submitted for a transaction. + * [DocumentSubmissionStatus](#documentsubmissionstatus) will always be `.completed` +````java +public void onSubmissionComplete(DocumentSubmissionStatus status) { + // present a basic alert to indicate completion + new AlertDialog.Builder(getActivity()) + .setTitle("Document Submission Complete") + .setMessage("All documents have been successfully submitted") + .create() + .show(); +} +```` + +3. `onSubmissionError(DocumentSubmissionError error)` + + + * Called when error occurs during SDK flow. + * Appropriate [DocumentSubmissionError](#documentsubmissionerror) is returned +````java +public void onSubmissionError(DocumentSubmissionError error) { + Log.e("onSubmissionError", error.getMessage()); +} + +```` + +### Class Reference + +### DocumentSubmissionResponse +`DocumentSubmissionResponse` object holds information pertaining to the document that was successfully submitted to the ID Verification service. + + +````java +public class DocumentSubmissionResponse implements Serializable{ + public func getDocumentStatus() -> [String: DocumentStatus] + public func getDocumentSubmissionStatus() -> DocumentSubmissionStatus + public Map getDocument() + public Date getCreatedAt() + public Date getUpdatedAt() + public Date getExpiresAt() +} +```` +`documentStatus` dictionary shows the status of each document requested. For example, if the requested documents for a certain transaction are the following: + +* Email + +* Phone + +* Selfie + +and the callback `oonDocumentSubmitted(DocumentSubmissionResponse response)` was fired after submitting `Email`, the `documentStatus` property will look like this: + +``` +["Email": .PROCESSED, "Phone": .REQUIRED, "Selfie", .REQUIRED] + +``` + +The list of `DocumentStatus` states can be found in [DocumentStatus](#documentstatus) + + +`documentSubmissionStatus` property shows the status of the entire verification transaction. Detailed information regarding `DocumentSubmissionStatus` can be found in [DocumentSubmissionStatus](#documentsubmissionstatus) + + +`document` dictionary holds information about the document that was just submitted to the ID Verification service. **Only applicable keys** are populated in the `document` dictionary + + +Data model of `document` + + +| Key | Description | +| --- | --- | +| `frontImage` | Base64 encoded string of the front image of a document | +| `backImage` | Base64 encoded string of the back image of a document | +| `barcode` | Barcode Data found on the document | +| `mrzData` | MRZData found on passport and other relevant document | +| `firstName` | User's first name as shown on the document | +| `middleName` | User's middle name as shown on the document | +| `lastName` | User's last name as shown on the document | +| `fullName` | User's full name | +| `additionalNameInfo` | Additional name info about the user | +| `addressStreet` | User's street address as shown on the document | +| `addressCity` | User's residence city as shown on the document | +| `addressState` | User's residence state as shown on the document | +| `addressZip` | User's ZIP Code as shown on the document | +| `country` | User's residence country as shown on the document | +| `sex` | User's sex as shown on the document | +| `dateOfBirth` | User's date of birth as shown on the document | +| `placeOfBirth` | User's place of birth as shown on the document | +| `nationality` | User's nationality as shown on the document | +| `maritalStatus` | User's marital status as shown on the document | +| `race` | User's race as shown on the document | +| `religion` | User's religion as shown on the document | +| `residentialStatus` | User's residential status as shown on the document | +| `documentNumber` | Document number as shown on the document | +| `documentAdditionalNumber` | Additional document number as shown on the document | +| `personalIdNumber` | Personal Id number as shown on the document | +| `dateOfIssue` | Date of issuance of the document | +| `dateOfExpiry` | Date of expiration of the document | +| `issuingAuthority` | Issuing authority of the document | +| `employer` | Employer as shown on the document | +| `profession` | Profession as shown on the document | + + +### DocumentStatus + +An enum describing the status of a particular document + + +````java +public enum DocumentStatus { + case REQUIRED, // document is required + case OPTIONAL, // document is optional; user may choose to skip + case COLLECTED, // document has been collected + case PROCESSED, // document has been processed + case SKIPPED; // document is skipped by user's choice +} +```` + +### DocumentSubmissionStatus + +An enum describing the status of the verification transaction + +````java +public enum DocumentSubmissionStatus implements Serializable { + @Json(name = "NOT_STARTED") NOT_STARTED, // transaction has not been initiated + @Json(name = "STARTED") STARTED,// transaction has been initiated, but not completed + @Json(name = "COMPLETED") COMPLETED, // transcation is being processed + @Json(name = "PROCESS") PROCESS // transaction has been processed and is completed +} +```` + +### SelfieCaptureSettings + +A configurable object to customize selfie capture experience + +````java +public class SelfieCaptureSettings { + public int captureTime; // selfie capture time (default is 45 seconds) + public boolean shouldCaptureAfterTimeout; // whether user should be able to capture selfie after timeout (default is true) +} + +```` + +### PingOne Verify SDK Errors +### ClientBuilderError +`ClientBuilderError` is returned when *PingOneVerify SDK* is initialized **incorrectly**. It subclasses `BuilderError` and `QRError` and is returned during `Builder.startVerification()` + + +### BuilderError + +| Error | Description | +| --- | --- | +| `"Must Set RootActivity"` | RootActivity was not set using `.setRootActivity(getActivity()))` in the builder | +| `"Must Set DocumentSubmissionListener"` | `DocumentSubmissionListener` was not set using `.setDocumentSubmissionListener(listener)` in the builder | + + +### QRError + +| Error | Description | +| --- | --- | +| `"Unable to parse queryItems from QR String: "` | Unable to parse QR Code | +| `"Missing verification code"` | QR Code is missing verification code | +| `"Missing TransactionId"` | QR Code is missing transactionId | + + +### DocumentSubmissionError + + +| Error | Description | +| --- | --- | +| `"Unable to initiate document transaction for transactionId:"` | Error when initiating a transaction | +| `"initiateDocumentCollection error"` | Error when submitting a document | +| `"There are no documents to submit for this transaction"` | No more documents to submit | +| `"Missing Document Type"` | Document type is missing | +| `"Invalid key map for documentType:"` | A valid key map for the document does not exist | +| `"Document Capture Error"` | Error when capturing the data | +| `"Missing OTP Destination for:"` | OTP Destination is missing | +| `Verification Code failed for %s` | OTP failed with invalid code | ### UI Customization @@ -53,6 +365,7 @@ UIAppearanceSettings |----------------------------------------------------------------------------------------|------------------------------------------------------------------| | `setLogoImage(Bitmap logoImage) -> UIAppearanceSetting` | Set logo image that is shown at the center of the navigation bar | | `setBackgroundColor(String backgroundColor) -> UIAppearanceSetting` | Set application background color | +| `setAppearanceProvider(AppearanceProvider appearanceProvider) -> UIAppearanceSetting` | Customise appearance settings(See [AppearanceProvider](#appearanceprovider))| | `setBodyTextColor(String bodyTextColor) -> UIAppearanceSetting` | Set body text color | | `setHeadingTextColor(String headingTextColor) -> UIAppearanceSetting` | Set heading text color | | `setNavigationBarColor(String navigationBarColor) -> UIAppearanceSetting` | Set navigation bar background color | @@ -61,6 +374,15 @@ UIAppearanceSettings | `setSolidButtonAppearance(ButtonAppearance solidButton) -> UIAppearanceSettings` | Set solid button appearance | | `setBorderedButtonAppearance(ButtonAppearance borderedButton) -> UIAppearanceSettings` | Set bordered button appearance | +### AppearanceProvider +The `AppearanceProvider` can be customized with the following methods to make additional changes to the User Interface. + +| Method | Description | +|----------------------------------------------------------------------------------------|------------------------------------------------------------------| +| `setShowSessionExpirationTimer(Boolean showTimer)` | Whether to show session timer, defaults to `true` | +| `setNavigationTitle(SpannableString navigationTitle)` | Set custom title-text, works with `setLogoImage(null)` | +| `setAttributedTexts(Map values)` | Use stylable texts for title & description texts for screens | + ### Customizing icon tint color If using custom image resources, set `PingOneVerifyClient.Builder(boolean isOverridingAssets)` to `true`. When the `isOverridingAssets` flag is `true`, the icon tint color is not applied to the custom images. @@ -101,3 +423,16 @@ For localization and messages, you can replace the values found in [localizable_ To customize resources such as icons/images, colors, localization strings, etc.: Include your custom resources such as drawables, colors, & strings in the respective `res` folder of your app + + +### Verify Policy + + + +PingOne Verify Native SDK utilizes Verify Policies. You can apply policies two ways: + + +* Use [Verify Policies](https://apidocs.pingidentity.com/pingone/platform/v1/api/#verify-policies) from the PingOne platform API. + + +* Use **Policies** tab found in *PingOne Admin Console -> PingOne Verify -> Policies* to customize verify policy for a particular environment. diff --git a/SDK/PingOneVerify-2.2.0.aar b/SDK/PingOneVerify-2.2.0.aar deleted file mode 100644 index 55a821c..0000000 Binary files a/SDK/PingOneVerify-2.2.0.aar and /dev/null differ diff --git a/SDK/PingOneVerify-2.3.3.aar b/SDK/PingOneVerify-2.3.3.aar new file mode 100644 index 0000000..2fecb98 Binary files /dev/null and b/SDK/PingOneVerify-2.3.3.aar differ diff --git a/SDK/iad.aar b/SDK/iad.aar index 5bb12c5..22ae828 100644 Binary files a/SDK/iad.aar and b/SDK/iad.aar differ diff --git a/SDK/voice_sdk.aar b/SDK/voice_sdk.aar index f16ac19..bb7706e 100644 Binary files a/SDK/voice_sdk.aar and b/SDK/voice_sdk.aar differ diff --git a/SampleCode/PingOneVerify/app/build.gradle b/SampleCode/PingOneVerify/app/build.gradle index d6594a2..c8f01bf 100644 --- a/SampleCode/PingOneVerify/app/build.gradle +++ b/SampleCode/PingOneVerify/app/build.gradle @@ -13,8 +13,8 @@ android { applicationId "com.pingidentity.sdk.pingoneverify.sample" minSdkVersion 26 targetSdkVersion 34 - versionCode 4 - versionName "2.2.0" + versionCode 8 + versionName "2.3.3" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } @@ -55,14 +55,13 @@ dependencies { implementation 'com.github.bumptech.glide:glide:4.13.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.13.0' - implementation 'com.google.android.material:material:1.12.0' implementation 'com.google.android.gms:play-services-mlkit-barcode-scanning:18.3.1' implementation 'com.google.android.gms:play-services-mlkit-face-detection:17.1.0' implementation 'com.google.code.gson:gson:2.10.1' - implementation 'com.google.protobuf:protobuf-kotlin-lite:3.20.1' implementation group: 'com.googlecode.libphonenumber', name: 'libphonenumber', version: '8.13.7' + implementation 'com.appmattus.certificatetransparency:certificatetransparency-android:1.1.1' implementation 'com.squareup.retrofit2:converter-moshi:2.7.2' implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.okhttp3:okhttp:4.9.3' @@ -71,7 +70,11 @@ dependencies { implementation 'com.squareup.moshi:moshi-kotlin:1.14.0' implementation group: 'com.squareup.okhttp3', name: 'okhttp-urlconnection', version: '4.9.3' - implementation("com.appmattus.certificatetransparency:certificatetransparency-android:1.1.1") + //Important: Below dependencies must be defined for Selfie/Government ID document upload on S3 + implementation 'org.bitbucket.b_c:jose4j:0.9.5' + //Important: Below dependencies should be defined for Selfie Liveness feature + implementation 'com.google.protobuf:protobuf-javalite:3.20.1' + implementation 'com.google.protobuf:protobuf-kotlin-lite:3.20.1' } configurations.implementation { diff --git a/SampleCode/PingOneVerify/app/proguard-rules.pro b/SampleCode/PingOneVerify/app/proguard-rules.pro index bf0c101..421da84 100644 --- a/SampleCode/PingOneVerify/app/proguard-rules.pro +++ b/SampleCode/PingOneVerify/app/proguard-rules.pro @@ -114,6 +114,9 @@ -keep public class com.google.android.gms.* { public *; } -dontwarn com.google.android.gms.** +-keep class org.jose4j.** { *; } +-dontwarn org.jose4j.** + #Adding missing proguard rules from missing_rules.txt -dontwarn com.google.protobuf.AbstractMessageLite -dontwarn com.google.protobuf.ByteString @@ -123,9 +126,11 @@ -dontwarn com.google.protobuf.GeneratedMessageLite$DefaultInstanceBasedParser -dontwarn com.google.protobuf.GeneratedMessageLite$MethodToInvoke -dontwarn com.google.protobuf.GeneratedMessageLite +-dontwarn com.google.protobuf.Internal$BooleanList -dontwarn com.google.protobuf.Internal$EnumLite -dontwarn com.google.protobuf.Internal$EnumLiteMap -dontwarn com.google.protobuf.Internal$EnumVerifier +-dontwarn com.google.protobuf.Internal$IntList -dontwarn com.google.protobuf.Internal$ProtobufList -dontwarn com.google.protobuf.InvalidProtocolBufferException -dontwarn com.google.protobuf.MessageLite @@ -135,3 +140,6 @@ -dontwarn com.google.protobuf.kotlin.DslList -dontwarn com.google.protobuf.kotlin.DslProxy -dontwarn com.google.protobuf.kotlin.ProtoDslMarker +-dontwarn org.slf4j.impl.StaticLoggerBinder +-dontwarn org.slf4j.impl.StaticMDCBinder +-dontwarn org.slf4j.impl.StaticMarkerBinder diff --git a/SampleCode/PingOneVerify/app/src/main/java/com/pingidentity/sdk/pingoneverify/sample/MainFragment.java b/SampleCode/PingOneVerify/app/src/main/java/com/pingidentity/sdk/pingoneverify/sample/MainFragment.java index 9eb7e6e..7957d52 100644 --- a/SampleCode/PingOneVerify/app/src/main/java/com/pingidentity/sdk/pingoneverify/sample/MainFragment.java +++ b/SampleCode/PingOneVerify/app/src/main/java/com/pingidentity/sdk/pingoneverify/sample/MainFragment.java @@ -1,6 +1,8 @@ package com.pingidentity.sdk.pingoneverify.sample; import android.app.AlertDialog; +import android.content.DialogInterface; +import android.graphics.Bitmap; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; @@ -10,20 +12,22 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.core.util.Consumer; import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentTransaction; import com.pingidentity.sdk.pingoneverify.PingOneVerifyClient; import com.pingidentity.sdk.pingoneverify.errors.DocumentSubmissionError; +import com.pingidentity.sdk.pingoneverify.listeners.BackActionHandler; import com.pingidentity.sdk.pingoneverify.listeners.DocumentSubmissionListener; import com.pingidentity.sdk.pingoneverify.models.DocumentSubmissionResponse; import com.pingidentity.sdk.pingoneverify.models.DocumentSubmissionStatus; import com.pingidentity.sdk.pingoneverify.settings.ButtonAppearance; import com.pingidentity.sdk.pingoneverify.settings.UIAppearanceSettings; +import com.pingidentity.sdk.pingoneverify.utils.BitmapUtils; -public class MainFragment extends Fragment implements DocumentSubmissionListener { +public class MainFragment extends Fragment implements DocumentSubmissionListener, BackActionHandler { - public static final String TAG = MainFragment.class.getCanonicalName(); + public static final String TAG = MainFragment.class.getName(); private Button mBtnVerify; private View waitOverlay; @@ -50,8 +54,7 @@ public void onDocumentSubmitted(DocumentSubmissionResponse response) { @Override public void onSubmissionComplete(DocumentSubmissionStatus status) { setInProgress(false); - getParentFragmentManager().beginTransaction() - .replace(R.id.frame_layout, new CompletedFragment()) + getParentFragmentManager().beginTransaction().replace(R.id.frame_layout, new CompletedFragment()) .addToBackStack(null) .commit(); } @@ -63,13 +66,26 @@ public void onSubmissionError(DocumentSubmissionError error) { setInProgress(false); } + /** + * @noinspection unused + */ // UIAppearanceSettings example + private UIAppearanceSettings getUiAppearanceSettings() { + Bitmap logoImage = BitmapUtils.getBitmap(requireContext(), R.mipmap.ic_launcher); + + return new UIAppearanceSettings() + .setLogoImage(logoImage) + .setSolidButtonAppearance(new ButtonAppearance("#F1C40F", "#F1C40F", "#95A5A6")) + .setBorderedButtonAppearance(new ButtonAppearance("#00FFFFFF", "#28B463", "#28B463")); + } + private void initPingOneClient() { waitOverlay.setVisibility(View.VISIBLE); new PingOneVerifyClient.Builder(false) .setRootActivity(getActivity()) .setListener(this) -// .setUIAppearance(this.getUiAppearanceSettings()) + .setBackActionHandler(this) +// .setUIAppearance(getUiAppearanceSettings()) .startVerification(new PingOneVerifyClient.Builder.BuilderCallback() { @Override public void onSuccess(PingOneVerifyClient client) { @@ -102,4 +118,24 @@ private void setInProgress(boolean inProgress) { mBtnVerify.setAlpha(inProgress ? 0.4f : 1f); } + @Override + public void onBackAction(Consumer consumer) { + new AlertDialog.Builder(getActivity()) + .setTitle(R.string.exit_transaction) + .setMessage(R.string.exit_the_transaction_prompt) + .setPositiveButton(R.string.exit_action_yes, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + consumer.accept(true); + } + }) + .setNegativeButton(R.string.exit_action_no, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + consumer.accept(false); + } + }) + .create() + .show(); + } } \ No newline at end of file diff --git a/SampleCode/PingOneVerify/app/src/main/res/drawable/ic_upload_success.xml b/SampleCode/PingOneVerify/app/src/main/res/drawable/ic_upload_success.xml index 8ed5af3..dc3e8c6 100644 --- a/SampleCode/PingOneVerify/app/src/main/res/drawable/ic_upload_success.xml +++ b/SampleCode/PingOneVerify/app/src/main/res/drawable/ic_upload_success.xml @@ -5,5 +5,5 @@ android:viewportHeight="138"> + android:fillColor="@color/black"/> diff --git a/SampleCode/PingOneVerify/app/src/main/res/values/PingOneVerifyLocalizable.xml b/SampleCode/PingOneVerify/app/src/main/res/values/PingOneVerifyLocalizable.xml index 443fd0d..d1eeb23 100644 --- a/SampleCode/PingOneVerify/app/src/main/res/values/PingOneVerifyLocalizable.xml +++ b/SampleCode/PingOneVerify/app/src/main/res/values/PingOneVerifyLocalizable.xml @@ -2,160 +2,151 @@ //QrScanner - Scan a PingOne QR Code - - //DocumentCapture - Submit - Step %1$d/%2$d + Please scan the above QR code //GovernmentID (Including both License and Passport) Scan your ID - Grab your photo ID. This can be a passport, driver’s license or any other government issued ID. Ensure the edges of your ID are in the frame and clearly visible. Hold it in your hand to avoid any glare. Pay attention to the live feedback. For some ID’s you may need to scan the back as well. - - // License - Capture Driver License - Verification requires a photo of the front and back of your government issued drivers license/ID. - - // Passport - Passport - Verification requires a photo page of your passport. + Scan your government-issued ID. Make sure your camera is clean and the ID is clearly visible. - // Voice - Record Your Voice - Make sure to sit in a quiet environment and bring your device closer to your mouth for recording your voice. - Get Started - Speak the following phrase into your device microphone: - Use PingOneVerify for voice verification + //Voice + Verify By Voice + Use your voice to verify your identity. + Tap record and say the following text: + Use your voice to verify your identity. Record Your Voice Tap to Record - Can’t continue without permission - Next Recording + Can\'t continue without permission + Next Record Voice Recording is Now Complete Recording Error - %1$d of %2$d Voice Sample Recording is Complete - Try Again - You will record 1 time. - You will record %1$s times. - Cancel + %1$d of %2$d + Complete Recorded speech was too short to process.\nPlease try again - Too much noise in the background.\nPlease try again in a more quiet setting - The audio recording has strong echo.\nPlease record in an another location + Recording Unclear + Recording Unclear Undetermined Error.\nPlease try again - // Selfie + //Selfie Take a Selfie - Center your face in the oval. Tap the button or anywhere on the screen to capture your selfie. + Make sure you can see your face in the oval. - // Email - Email Verification - "Please enter your email address" - "Please choose your email address" - "Email to be verified:" + //Email + Verify Your Email + Enter your email address. + Please choose your email address + Email to be verified Email Address - Submit - // Phone - Phone Verification - "Please enter your phone number" - "Please choose your phone number" - "Phone number to be verified:" - Phone number… + //Phone + Verify Your Phone + Enter your phone number. + Please choose your phone number + Phone number to be verified + Enter phone number Select a country Search - Submit //OTP Verification Code - Verification Code - Resend Verification Code - Submit Passcode - Please type the Verification Code sent to %1$s + Enter the code sent to: Verification Code expires in %1$s %1$d min %1$d sec - your Email Address - your Phone Number - //Buttons Skip + Continue Submit Next + Retry + Cancel + Resend + Yes, Continue + No, Retake Permission not granted - Access to the camera is required for scanning your IDs and taking pictures.\n\nPlease update the permissions for your app in device settings to be able to use this feature. + Cannot access camera + Location not enabled + Access to your camera is needed to scan your ID and take your selfie. Access to the microphone is required for voice verification.\n\nPlease update the permissions for your app in device settings to be able to use this feature. - Retry + Enable location permission to proceed with your identity verification. Settings - Cancel - //Common - Selfie - Driver License - Passport + Verification Error + Is it clear? + Is it readable? + Processing Session expires in %1$s - ImageView Content Description - - (%1$s)-%2$s - - One Time Passcode is incorrect - Error confirming your verification code - - Re-take - Submit - - - - Make sure that both eyes are open - - - Center your face in the frame - Hold your phone closer to your face - Hold your phone further away from your face - Face the camera - Tap anywhere on the screen to capture image - Keep your head straight - Close your mouth - - Cannot capture selfie - - Exceeded the Selfie Capture timeout limit. Please try again. - - - - - - - - Whoops, missed it. Please try again. - No Face Detected - Multiple faces in the frame - Different face in the frame + You entered an incorrect code. Please try again. + Error confirming your verification code + //IDRnD FaceLive + Make sure your face is clearly visible in the camera. + Multiple faces detected + Move camera closer + Center your face in the green oval and try again. + Center face in frame + Position in front of face + Move the camera farther away from your face and try again. + Please hold your device still + Remove any masks, hats, or anything covering your face from the camera. //Blink ID - Scan the front side of the document + Scan or upload an image of the front of your ID Scan the barcode - Flip to the back side + Scan or upload an image of the back of your ID Move closer Move farther Move the document from the edge Keep all the details visible Close Please start the scanning process over. - Sides don’t match + Sides don\'t match Keep the document fully visible Watch out for flashlight glare.\nGently move your ID around to avoid it. Unable to read the document. Please try again. Retry Scan unsuccessful Scanning not available - Something went wrong - Slightly move ID to eliminate glare. + Something went wrong. Please refresh and try again. + Tilt or move document to remove reflections It appears the information on the document is inconsistent. Please try scanning again. Please make sure you are scanning a supported ID. Invalid ID + //MB Error Messages Please make sure you are scanning your %1$s. - \ No newline at end of file + Make sure your camera lens is clean and all four corners of the ID are visible. + Make sure the ID is not reflecting direct light and is in focus. + Go to a well-lit environment. Make sure the ID is in focus, without glare, and then retry. + Make sure your camera lens is clean and all four corners of the ID are visible. + Document images don\'t match. + Move the camera closer, making sure all four corners of the ID are visible. + Make sure your camera lens is clean and all four corners of the ID are visible + Move the camera farther away from your face and try again. + Center your face in the green oval and try again. + Center your face in the green oval and try again. + Remove any masks, hats, or anything covering your face from the camera. + Make sure your face is clearly visible in the camera. + Make sure your face is clearly visible in the camera + Make sure only your face appears in the camera and then retry. + Move the camera closer to your face and try again. + Position the camera directly in front of your face and try again. + Make sure your eyes are not closed and try again. + + //Indian Aadhaar + Verify Aadhaar ID + Confirm or edit your Aadhaar ID. + Aadhaar ID. + Enter OTP + Enter the one-time password that was sent to the phone number associated with the Aadhaar ID. + Confirm ID Type + We couldn\'t identify your ID.\nSelect the ID type to continue. + Indian Aadhaar Card + Driver\'s License + Passport + Passport Card + Other + Incorrect password. Try again. + diff --git a/SampleCode/PingOneVerify/app/src/main/res/values/colors.xml b/SampleCode/PingOneVerify/app/src/main/res/values/colors.xml index 0f9d9d9..e3600f9 100644 --- a/SampleCode/PingOneVerify/app/src/main/res/values/colors.xml +++ b/SampleCode/PingOneVerify/app/src/main/res/values/colors.xml @@ -8,6 +8,7 @@ #FF000000 #FFFFFFFF #458EBF + #33D3D3D3 #4462ED #253746 diff --git a/SampleCode/PingOneVerify/app/src/main/res/values/dimens.xml b/SampleCode/PingOneVerify/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000..ed97e74 --- /dev/null +++ b/SampleCode/PingOneVerify/app/src/main/res/values/dimens.xml @@ -0,0 +1,5 @@ + + + 30sp + 18sp + \ No newline at end of file diff --git a/SampleCode/PingOneVerify/app/src/main/res/values/plurals.xml b/SampleCode/PingOneVerify/app/src/main/res/values/plurals.xml new file mode 100644 index 0000000..d4fb487 --- /dev/null +++ b/SampleCode/PingOneVerify/app/src/main/res/values/plurals.xml @@ -0,0 +1,7 @@ + + + + You will record %1$s time. + You will record %1$s times. + + \ No newline at end of file diff --git a/SampleCode/PingOneVerify/app/src/main/res/values/strings.xml b/SampleCode/PingOneVerify/app/src/main/res/values/strings.xml index be064cf..77f6946 100644 --- a/SampleCode/PingOneVerify/app/src/main/res/values/strings.xml +++ b/SampleCode/PingOneVerify/app/src/main/res/values/strings.xml @@ -1,12 +1,16 @@ - //Main PingOneVerify - Configuration + //Main Begin Verification - PingOne Verify Test App - Document Verification Requested - We need to confirm your identity. This will require scanning your government issued ID such as a Driver License or Passport. Please have your ID ready before proceeding and in a well lit environment for best results. + Verification Requested + We need to confirm your identity. Follow the prompts to complete verification. //Completed - Verification Complete - We have gathered all the information required to continue the verification process. You can close this tab now. - \ No newline at end of file + Complete + You\'ve submitted everything required for verification + + Exit Transaction + Are you sure you want to exit this process? + Yes + No + +