The following documentation explains what has changed between v1.1.0 and v2.x.x of the Android SDK and what to consider when migrating to the latest version.
Changes in v2.x.x
We have updated the parameters that are returned on payment completion. This now includes:
- List of request responses.
- The field threedresponse (if present).
- Any errors that have occurred.
data class Response(
val responseJwtList: List<String> = emptyList(),
val threeDResponse: ThreeDResponse? = null,
val error: Error? = null)
sealed class PaymentSessionResponse {
sealed class Failure(): PaymentSessionResponse() {
/**
* Errors representing illegal states on payment session initialization and execution. They
* indicate merchant's development errors, which should never occur on production environment.
*/
sealed class DeveloperError(val message: String): Failure() {
object SessionAlreadyExecuted: DeveloperError("This session has already been executed")
object InvalidRequestTypes: DeveloperError("Invalid request types provided in JWT payload")
object ActivityProviderRequired: DeveloperError("Providing activityProvider parameter is mandatory if request list contains THREEDQUERY")
object ActivityResultProviderRequired: DeveloperError("Providing activityResultProvider parameter is mandatory if request list contains THREEDQUERY")
}
/**
* Generic error was returned for initialization or Cardinal initialization.
*/
object InitializationError: Failure()
/**
* Error or ParsingError was returned as TransactionResponse for initialization.
*/
data class InitializationFailure(val jwt: String, val result: TransactionResponse): Failure()
/**
* Error returned when any safety warnings have been detected by Cardinal SDK.
*/
data class SafetyError(val errors: List<DeviceSafetyWarning>): Failure()
/**
* At least one transaction returned Error or ParsingError.
*/
data class TransactionFailure(val responseParts: List<ResponsePart<TransactionResponse>>): Failure() {
val allResponses: List<TransactionResponse>
get() = responseParts.flatMapTo(arrayListOf()) { it.responses }
}
}
data class Success(val responseParts: List<ResponsePart<TransactionResponse.PaymentSuccess>>): PaymentSessionResponse() {
val allResponses: List<TransactionResponse.PaymentSuccess>
get() = responseParts.flatMapTo(arrayListOf()) { it.responses }
}
}
In v1.1.0, as part of the Success and TransactionFailure objects, we returned a parsed transaction response object.
However, in v2.x.x, we only have one Response object, because we wanted to provide our merchants more control over how they interpret the response.
Example scenario
In v1.1.0, a request of “THREEDQUERY”,”AUTH”,”SUBSCRIPTION” where the THREEDQUERY and AUTH were successful, but the SUBSCRIPTION encountered an error, then the SDK would return a TransactionFailure object, despite the THREEDQUERY and AUTH having been processed successfully. Displaying an error message to the customer in this particular scenario may be misleading, because funds had been reserved against their bank account.
To reduce the chance of the customer being misinformed about the result of the payment transaction, in v2.x.x we no longer distinguish between success and failure in this way, and we will now only return the full list of results that you must first verify, parse and then analyse the errorcode returned in each of the responses.
In regards to the scenario above, you could configure your system to treat the THREEDQUERY and AUTH responses as a success and display the appropriate response message in the customer’s browser (to indicate funds were reserved for payment), but also display an error message to inform them that the automated subscription payments have yet to be scheduled due to an error, and that the customer is recommended to contact you for assistance.
Before information in the response object can be trusted, you must verify the signature of each JWT response.
We provide a parsing utility to extract the payload field data as part of reviewing the payment response fields:
(Kotlin)
val response: PaymentTransactionManager.Response = paymentTransactionManager.executeSession(paymentSession)
//Every JWT returned from the SDK should be verified before further usage.
for (jwt in response.responseJwtList) {
if (!verifyJwtIntegrity(jwt)) {
throw SecurityException("JWT verification failed!")
}
}
val parsedResponse = ResponseParser.parse(response.responseJwtList)
//Process parsedResponse object in a similar manner as in v1.1.0