When processing payments using the Ryft Android Drop-In SDK, there may be scenarios where additional client-side actions are required to complete the payment. These actions can include 3D Secure authentication, handling redirects, or other verification steps mandated by the card issuer or payment method.
Our Drop-In SDK is designed to handle these client-side actions seamlessly, providing a smooth user experience. However, you may want to handle any required client-side actions explicitly in your application code.
A common use case would be a MIT payment where the card issuer requires 3D Secure authentication to complete the transaction. In such cases, you will need to bring the customer back to your application after they complete the authentication process.
To handle client-side actions in your application, you can use our RyftRequiredActionComponent object. This component provides methods to manage and execute the required actions.
Similarly to the Drop-In, you can initialise the component within the fragment or activity that handles your checkout process within the onCreate method.
Here's an example of how to initialise the Ryft Required Action Component in your activity:
class CheckoutFragment : Fragment() {
// ...
// Declare RyftRequiredActionComponent
private lateinit var ryftRequiredActionComponent: RyftRequiredActionComponent
// ...
// Instantiate DefaultRyftRequiredActionComponent in onCreate()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// ...
ryftRequiredActionComponent = DefaultRyftRequiredActionComponent(
// The calling fragment (activity is also supported)
fragment = this,
// The class you want to listen for the result (see "Implementing the RyftRequiredActionResultListener" below)
listener = this
)
// ...
}
// ...
}In order to handle the required action, you can simply call the handle() method on the RyftRequiredActionComponent instance you created during the initialisation step. This will include passing the necessary parameters required for the action process, such as:
- the Client Secret obtained from your backend when creating a Payment Session;
- the Public Key;
Here's an example of how to handle the required action in your activity or fragment:
class CheckoutFragment : Fragment() {
// ...
// Example function to handle the required action
// Fetch 'requiredAction' from your backend
private fun handleRequiredAction(requiredAction: RequiredAction) {
ryftRequiredActionComponent.handle(
RyftRequiredActionComponent.Configuration.standardAccountPayment(
clientSecret = "", // The client secret returned when creating a Payment Session
publicApiKey = RyftPublicApiKey("") // Your Ryft Public API Key
),
requiredAction
)
}
// ...
}Once the handle() method is called, the Ryft Required Action Component will process the required action. To receive the result of this process, you need to implement the RyftRequiredActionResultListener interface in your activity or fragment:
interface RyftRequiredActionResultListener {
fun onRequiredActionResult(result: RyftRequiredActionResult)
}This method is invoked when the required action process is completed, allowing you to handle the result accordingly.
The RyftRequiredActionResult object has two possible outcomes that you can handle:
| State | Description | Action Required |
|---|---|---|
| Success | The required action was handled successfully, and the payment can proceed (the 3DS result may have been successful or failed). | Inspect the status of the Payment Session to determine the next steps. |
| Error | An error occurred while handling the required action. | Display an error message to the user and allow them to retry (which should involve handling the required action again). |
Here's an example of how to implement the RyftRequiredActionResultListener in your activity or fragment:
class CheckoutFragment : Fragment(), RyftDropInResultListener {
// ...
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// ...
ryftRequiredActionComponent = DefaultRyftRequiredActionComponent(
fragment = this,
listener = this // This fragment will listen for the dropin result
)
// ...
}
// ...
override fun onRequiredActionResult(result: RyftRequiredActionResult) = when (result) {
// The required action was handled successfully - inspect the status to determine the next step
// `result.paymentSession` returns the updated payment session
is RyftRequiredActionResult.Success -> {
val status = result.paymentSession.status
// ...
}
// There was an error whilst handling the required action - show an alert to the customer
// `result.error.displayError` provides a human friendly message you can display
is RyftRequiredActionResult.Error -> {
AlertDialog.Builder(requireContext())
.setTitle("Error taking payment")
.setMessage(result.error.displayError)
.setPositiveButton("Try again") { _, _ ->
// Fetch the latest 'requiredAction' from your backend
handleRequiredAction(requiredAction)
}
.setNegativeButton("Cancel") { dialog, _ ->
dialog.dismiss()
}
.create()
.show()
}
}
// ...
}Once the payment has been processed successfully, you can proceed to show a confirmation screen to the user or handle any post-payment logic as needed.
It is also recommended to set up webhooks on your backend to listen for payment events and update your records accordingly. For more information on setting up webhooks, please refer to the Webhooks Documentation section.