Skip to content

Latest commit

 

History

History
837 lines (630 loc) · 20.1 KB

File metadata and controls

837 lines (630 loc) · 20.1 KB

FIA Documentation (Android)

Documentation on how to use FIA Android SDK.

Installation

Add the dependency in your app-level build.gradle (project/app/build.gradle)

dependencies {
	// Another dependencies...
	implementation 'com.fazpass:fia:1.1.8'
}

Then sync project with gradle files.

Getting Started

Before using this SDK, make sure to get the Merchant Key and Merchant App ID from Keypaz Dashboard. Check this Dashboard Documentation.

Setup Miscall

Miscall needs these two permissions:

  • Manifest.permission.READ_PHONE_STATE
  • Manifest.permission.READ_CALL_LOG

Add these lines in your android manifest file:

<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />

Then request for runtime permissions like this:

Kotlin
val requiredPermissions = arrayOf(Manifest.permission.READ_PHONE_STATE, Manifest.permission.READ_CALL_LOG)
ActivityCompat.requestPermissions(this, requiredPermissions, 0)
Java
String[] requiredPermissions = { Manifest.permission.READ_PHONE_STATE, Manifest.permission.READ_CALL_LOG };
ActivityCompat.requestPermissions(this, requiredPermissions, 0);

Setup HE

Add this line in your android manifest file, in the application tag:

android:networkSecurityConfig="@xml/fia_network_security_rules"

Example

<application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:networkSecurityConfig="@xml/fia_network_security_rules">

	<!-- Your declared activity tags, service tags etc. -->
</application>
Already had a network security config rules in your app?

Then this is the configuration needed for FIA:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>

	<!-- other domain configurations... -->

	<domain-config cleartextTrafficPermitted="true">
		<domain includeSubdomains="true">verify.klikaman.online</domain>
		<domain includeSubdomains="true">api.fazpass.com</domain>
		<trust-anchors>
			<certificates src="system" />
			<certificates src="user" />
		</trust-anchors>
	</domain-config>
</network-security-config>

Setup Magic Link

Add this code in your android manifest file, inside the application tag:

<activity
    android:name="com.fazpass.fia.activities.magiclink.MagicLinkActivity"
    android:exported="true">
    <intent-filter android:autoVerify="true">
	<action android:name="android.intent.action.VIEW" />

	<category android:name="android.intent.category.DEFAULT" />
	<category android:name="android.intent.category.BROWSABLE" />

	<data
	    android:host="YOUR_DOMAIN"
	    android:scheme="https" />
    </intent-filter>
</activity>

Fill YOUR_DOMAIN with your website domain.

Then create a new file named assetlinks.json with this content:

[
  {
    "relation": ["delegate_permission/common.handle_all_urls"],
    "target": {
      "namespace": "android_app",
      "package_name": "YOUR_PACKAGE_NAME",
      "sha256_cert_fingerprints": ["YOUR_SHA256_CERT_FINGERPRINT"]
    }
  }
]

Fill YOUR_PACKAGE_NAME with your app package name (example: com.example.app), YOUR_SHA256_CERT_FINGERPRINT with your app SHA256 certificate fingerprint.

How to get your app SHA256 Certificate Fingerprint

In assetlinks.json, sha256_cert_fingerprints is an array. You can add more than one certificate fingerprints in here.

  1. Follow this Android App Signing Documentation up until you created a keystore
  2. Run this command in your console to check your keystore (.jks or .keystore) information: keytool -list -v -keystore MY_KEYSTORE.jks
  3. Enter your keystore password
  4. Console will print out your keystore information. Copy the SHA256 certificate fingerprints value
  5. Add the certificate fingerprint to the sha256_cert_fingerprints array
  6. After you uploaded your app to Playstore, open Google Play Console
  7. Navigate to your app > Test & Release > App Integrity > App Signing
  8. Copy the SHA256 certificate fingerprints value
  9. If the value is different from the first one, add the certificate fingerprint to the sha256_cert_fingerprints array

Then save the assetlinks.json file and serve it in your domain with this link: https://YOUR_DOMAIN.com/.well-known/assetlinks.json. Make sure:

  1. It's available for public access
  2. No Redirect
  3. Content-Type is application/json

Usage

First, you have to initialize the sdk once.

Kotlin
import com.fazpass.fia.FIAFactory

// get fia instance
val fia = FIAFactory.getInstance()

fia.initialize(this, "YOUR_MERCHANT_KEY", "YOUR_MERCHANT_APP_ID")
Java
import com.fazpass.fia.FIAFactory;
import com.fazpass.fia.interfaces.FIA;

// get fia instance
FIA fia = FIAFactory.getInstance();

fia.initialize(this, "YOUR_MERCHANT_KEY", "YOUR_MERCHANT_APP_ID");

There are two ways to request an OTP:

  1. With premade activity
    If you want to request an OTP without making any view/UI for the OTP activity.
  2. With custom-made activity
    If you want to make your own view/UI for the OTP activity.

Request OTP with a premade activity

Requesting an OTP with premade activity is easier than requesting an OTP with custom-made activity. Use this one if you don't want to make your own view/UI.

1. Create a class-level variable with type OtpActivitySettings

Then assign this variable in the activity onCreate() method with fia.otpActivity(this).

Kotlin
import com.fazpass.fia.FIAFactory
import com.fazpass.fia.objects.OtpActivitySettings

class MainActivity: AppCompatActivity() {

	private val fia = FIAFactory.getInstance()

	// class-level variable
	private lateinit var otp: OtpActivitySettings

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

		// If FIA has not been initialized once, uncomment the line below.
		// fia.initialize(this, "YOUR_MERCHANT_KEY", "YOUR_MERCHANT_APP_ID")
		otp = fia.otpActivity(this)
	}
}
Java
import com.fazpass.fia.FIAFactory;
import com.fazpass.fia.interfaces.FIA;
import com.fazpass.fia.objects.OtpActivitySettings;

public class MainActivity extends AppCompatActivity {

	private final FIA fia = FIAFactory.getInstance();

	// class-level variable
	private OtpActivitySettings otp;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		// If FIA has not been initialized once, uncomment the line below.
		// fia.initialize(this, "YOUR_MERCHANT_KEY", "YOUR_MERCHANT_APP_ID");
		otp = fia.otpActivity(this);
	}
}

2. Launch the OTP activity

To launch the OTP activity, call one of the four methods which fits the purpose of the otp:

  • login()
  • register()
  • transaction()
  • forgetPassword()

For example, we will use the login method.

Kotlin
otp.login("PHONE_NUMBER") { transactionId: String? ->
	// If transactionId is null, OTP validation has an error.
	if (transactionId == null) {
		// handle failed OTP validation here...
		return@login 
	}

	// with the transactionId, check for the user verified status here...
}
Java
otp.login("PHONE_NUMBER", transactionId -> {
	// If transactionId is null, OTP validation has an error.
	if (transactionId == null) {
		// handle failed OTP validation here...
		return null;
	}

	// with the transactionId, check for the user verified status here...
	return null;
});

3. Check for user verified status

Get the transactionId, then check the segment down below on how to check if user has been successfully verified.

Request OTP with a custom-made activity

Unlike requesting OTP with premade activity, you don't have to assign the variable in the activity onCreate() method. Also, there are more steps involved.

1. Create a public class to hold a static variable of type OtpPromise

Kotlin
import com.fazpass.fia.objects.OtpPromise

class Constants {
	companion object {
		lateinit var otpPromise: OtpPromise
	}
}
Java
import com.fazpass.fia.objects.OtpPromise;

public class Constants {
	public static OtpPromise otpPromise;
}

2. Request for an OTP

To request for an OTP, call one of the four methods which fits the purpose of the otp:

  • login()
  • register()
  • transaction()
  • forgetPassword()

For example, we will use the register method.

Kotlin
fia.otp(this).register("PHONE_NUMBER") { promise ->
	if (promise.hasException) {
		val exception = promise.exception
		// handle failed OTP request here...
		return@register 
	}

	Constants.otpPromise = promise
}
Java
fia.otp(this).register("PHONE_NUMBER", promise -> {
	if (promise.getHasException()) {
		Exception exception = promise.getException();
		// handle failed OTP request here...
		return null;
	}

	Constants.otpPromise = promise;
	return null;
})

3. Check which OTP type was being used with otpPromise.authType

Here, you can launch between activities according to their authentication type as described in the example below.

Kotlin
import com.fazpass.fia.objects.OtpAuthType

when (Constants.otpPromise.authType) {
	OtpAuthType.HE -> {
		val intent = Intent(this@MainActivity, ValidateHEActivity::class.java)
		startActivity(intent)
	}
	OtpAuthType.Miscall -> {
		val intent = Intent(this@MainActivity, ValidateMiscallActivity::class.java)
		startActivity(intent)
	}
	OtpAuthType.SMS -> {
		val intent = Intent(this@MainActivity, ValidateSMSActivity::class.java)
		startActivity(intent)
	}
	OtpAuthType.Whatsapp -> {
		val intent = Intent(this@MainActivity, ValidateWhatsappActivity::class.java)
		startActivity(intent)
	}
	OtpAuthType.MagicOtp -> {
		val intent = Intent(this@MainActivity, ValidateMagicOtpActivity::class.java)
		startActivity(intent)
	}
	OtpAuthType.MagicLink -> {
		val intent = Intent(this@MainActivity, ValidateMagicLinkActivity::class.java)
		startActivity(intent)
	}
}
Java
import com.fazpass.fia.objects.OtpAuthType;

switch (Constants.otpPromise.getAuthType()) {
	case OtpAuthType.HE:
		Intent intent = new Intent(MainActivity.this, ValidateHEActivity.class);
		startActivity(intent);
		break;
	case OtpAuthType.Miscall:
		Intent intent = new Intent(MainActivity.this, ValidateMiscallActivity.class);
		startActivity(intent);
		break;
	case OtpAuthType.SMS:
		Intent intent = new Intent(MainActivity.this, ValidateSMSActivity.class);
		startActivity(intent);
		break;
	case OtpAuthType.Whatsapp:
		Intent intent = new Intent(MainActivity.this, ValidateWhatsappActivity.class);
		startActivity(intent);
		break;
	case OtpAuthType.MagicOtp:
		Intent intent = new Intent(MainActivity.this, ValidateMagicOtpActivity.class);
		startActivity(intent);
		break;
	case OtpAuthType.MagicLink:
		Intent intent = new Intent(MainActivity.this, ValidateMagicLinkActivity.class);
		startActivity(intent);
		break;
}

Recently, there are 6 auth type:

HE auth type

HE (Header Enrichment) uses network to verify the user. User will not receive an OTP and does not need to input any OTP. Only available if user uses data carrier for internet.

To validate this auth type, call validateHE() method. First callback will be fired if there is an error. Second callback will be fired if validation has been successful.

Kotlin
Constants.otpPromise.validateHE(
	{ err ->
		// handle error here...
	},
	{
		val transactionId = Constants.otpPromise.transactionId
		// with the transactionId, check for the user verified status here...
	}
)
Java
Constants.otpPromise.validateHE(
	err -> {
		// handle error here...
	},
	() -> {
		String transactionId = Constants.otpPromise.getTransactionId();
		// with the transactionId, check for the user verified status here...
	}
)

Miscall auth type

This OTP will call user's phone number.

User has to fill the last several digits of the caller's phone number. Digit count can be obtained with digitCount property. There is also a miscall listener method listenToMiscall(). See code snippet down below for example usage.

To validate this auth type, call validate() method and fill the inputted user OTP in the parameter. First callback will be fired if there is an error. Second callback will be fired if validation has been successful.

Kotlin
val digitCount = Constants.otpPromise.digitCount

// miscall OTP listener
Constants.otpPromise.listenToMiscall { otp ->
	// validate OTP method
	Constants.otpPromise.validate(
		otp,
		{ err ->
			// handle error here...
		},
		{
			val transactionId = Constants.otpPromise.transactionId
			// with the transactionId, check for the user verified status here...
		}
	)
}
Java
Int digitCount = Constants.otpPromise.getDigitCount();

// miscall OTP listener
Constants.otpPromise.listenToMiscall(otp -> {
	// validate OTP method
	Constants.otpPromise.validate(
		otp,
		err -> {
			// handle error here...
			return null;
		},
		() -> {
			String transactionId = Constants.otpPromise.getTransactionId();
			// with the transactionId, check for the user verified status here...
			return null;
		}
	);
	return null;
});

SMS auth type

This OTP will send an SMS to user's phone number.

User has to fill the OTP sent to their SMS inbox. Digit count can be obtained with digitCount property.

To validate this auth type, call validate() method and fill the inputted user OTP in the parameter. First callback will be fired if there is an error. Second callback will be fired if validation has been successful.

Kotlin
val digitCount = Constants.otpPromise.digitCount

Constants.otpPromise.validate(
	"USER_INPUTTED_OTP",
	{ err ->
		// handle error here...
	},
	{
		val transactionId = Constants.otpPromise.transactionId
		// with the transactionId, check for the user verified status here...
	}
)
Java
Int digitCount = Constants.otpPromise.getDigitCount();

Constants.otpPromise.validate(
	"USER_INPUTTED_OTP",
	err -> {
		// handle error here...
		return null;
	},
	() -> {
		String transactionId = Constants.otpPromise.getTransactionId();
		// with the transactionId, check for the user verified status here...
		return null;
	}
);

Whatsapp auth type

This OTP will send a Whatsapp message to user's Whatsapp number.

User has to fill the OTP sent to their Whatsapp. Digit count can be obtained with digitCount property.

To validate this auth type, call validate() method and fill the inputted user OTP in the parameter. First callback will be fired if there is an error. Second callback will be fired if validation has been successful.

Kotlin
val digitCount = Constants.otpPromise.digitCount

Constants.otpPromise.validate(
	"USER_INPUTTED_OTP",
	{ err ->
		// handle error here...
	},
	{
		val transactionId = Constants.otpPromise.transactionId
		// with the transactionId, check for the user verified status here...
	}
)
Java
Int digitCount = Constants.otpPromise.getDigitCount();

Constants.otpPromise.validate(
	"USER_INPUTTED_OTP",
	err -> {
		// handle error here...
		return null;
	},
	() -> {
		String transactionId = Constants.otpPromise.getTransactionId();
		// with the transactionId, check for the user verified status here...
		return null;
	}
);

Magic Otp auth type

User will be redirected to Whatsapp and required to send a prepared message to a specified phone number. Then user has to input the incoming OTP from their Whatsapp to your application.

With this auth type, call launchWhatsappForMagicOtp() method to launch Whatsapp. First callback will be fired if there is an error when launching Whatsapp. Second callback will be fired if Whatsapp launched successfully.

After Whatsapp has been launched successfully, you can validate the OTP using validate() method. Check documentation about Whatsapp auth type above.

Kotlin
Constants.otpPromise.launchWhatsappForMagicOtp(
	{ err ->
		// handle error here...
	},
	{
		// show user a textfield to input the incoming OTP,
		// then call the validate Whatsapp method (Constants.otpPromise.validate())
	}
)
Java
Constants.otpPromise.launchWhatsappForMagicOtp(
	err -> {
		// handle error here...
		return null;
	},
	() -> {
		// show user a textfield to input the incoming OTP,
		// then call the validate Whatsapp method (Constants.otpPromise.validate())
		return null;
	}
);

Magic Link auth type

User will be redirected to Whatsapp and required to send a prepared message to a specified phone number. Then user has to click on the link from their Whatsapp.

With this auth type, call launchWhatsappForMagicLink() method to launch Whatsapp. First callback will be fired if there is an error. Second callback will be fired if validation has been successful.

Kotlin
Constants.otpPromise.launchWhatsappForMagicLink(
	{ err ->
		// handle error here...
	},
	{
		val transactionId = Constants.otpPromise.transactionId
		// with the transactionId, check for the user verified status here...
	}
)
Java
Constants.otpPromise.launchWhatsappForMagicLink(
	err -> {
		// handle error here...
		return null;
	},
	() -> {
		String transactionId = Constants.otpPromise.getTransactionId();
		// with the transactionId, check for the user verified status here...
		return null;
	}
);

4. Check for user verified status

Get the transactionId like this:

Kotlin
val transactionId = Constants.otpPromise.transactionId
Java
String transactionId = Constants.otpPromise.getTransactionId();

Then check the segment down below on how to check if user has been successfully verified.

Important note

Caution

You have to call method otpActivity() directly in the activity onCreate() method. Otherwise your app might crash.

Caution

You have to call method otpActivity() or otp() using FragmentActivity OR AppCompatActivity as context. Otherwise your app might crash.

Tip

If you use android jetpack compose for UI builder, it's okay to change ComponentActivity to one of these activities. Because AppCompatActivity extends FragmentActivity, which extends ComponentActivity. See the reference here.

Check for user verified status

A successfully validated OTP DOES NOT mean that the user has also been successfully verified. To check for user's verified status, check this Server Documentation.