SEPA Direct Debit

Client-Side Implementation

Availability

SEPA Direct Debit is available to eligible merchants using a custom client-side integration. It is only available in Android v4.13+, iOS v5.11+, and JavaScript v3 SDK. It's not currently available in Drop-in.

If you meet the criteria, Contact us to enable SEPA Direct Debit in your Sandbox or Production account.

Get the SDKAnchorIcon

Add the following in your app-level build.gradle:

  1. Kotlin
  2. Groovy
dependencies {
    implementation("com.braintreepayments.api:sepa-direct-debit:5.8.0")
}

Collect informationAnchorIcon

Once your component is ready, collect the required bank account information from the customer.

Bank information:

  • accountHolderName (the name of the account owner)
  • iban (International Bank Account Number)

Customer information:

  • billingAddress
  • customerId (customer id in the merchant's system)

Invoking the SEPA Direct Debit flowAnchorIcon

Construct a SEPADirectDebitClient, SEPADirectDebitLauncher and a SEPADirectDebitRequest. Call SEPADirectDebitClient.createPaymentAuthRequest() to launch the SEPA Direct Debit flow and call SEPADirectDebitLauncher.launch(). Finally, handle the result and call SEPADirectDebitClient.tokenize() and handle its result.

  1. Kotlin
class MyActivity : AppCompatActivity() {

    private lateinit var sepaDirectDebitLauncher: SEPADirectDebitLauncher
    private lateinit var sepaDirectDebitClient: SEPADirectDebitClient

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

        sepaDirectDebitLauncher = SEPADirectDebitLauncher()
        sepaDirectDebitClient = SEPADirectDebitClient(
            context = this,
            authorization = "TOKENIZATION_KEY or CLIENT_TOKEN",
            returnUrlScheme = "RETURN_URL_SCHEME"
        )
    }

    // ALL OTHER ACTIVITY LAUNCH MODES
    override fun onResume() {
        super.onResume()
        handleReturnToApp(intent)
    }

    // ONLY REQUIRED IF YOUR ACTIVITY LAUNCH MODE IS SINGLE_TOP
    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        handleReturnToApp(intent)
    }

    private fun handleReturnToApp(intent: Intent) {
        // fetch stored SEPADirectDebitPendingRequest.Started
        val pendingRequest: String = fetchPendingRequestFromPersistantStore()
        when (val paymentAuthResult = sepaDirectDebitLauncher.handleReturnToApp(
            pendingRequest = SEPADirectDebitPendingRequest.Started(pendingRequest),
            intent = intent
        )) {
            is SEPADirectDebitPaymentAuthResult.Success -> {
                completeSepaFlow(paymentAuthResult)
                // clear stored pending request
            }

            is SEPADirectDebitPaymentAuthResult.NoResult -> {
                // user returned to app without completing the flow, handle accordingly
            }

            is SEPADirectDebitPaymentAuthResult.Failure -> {
                // handle error case
            }
        }
    }

    private fun completeSepaFlow(paymentAuthResult: SEPADirectDebitPaymentAuthResult.Success) {
        sepaDirectDebitClient.tokenize(paymentAuthResult) { result ->
            when (result) {
                is SEPADirectDebitResult.Success -> {
                    // send result.nonce.string to server and create a transaction
                }
                is SEPADirectDebitResult.Failure -> { /* handle result.error */ }
                is SEPADirectDebitResult.Cancel -> { /* handle user canceled */ }
            }
        }
    }

    private fun startSEPADirectDebit() {
        val billingAddress = PostalAddress(
            recipientName = "John Doe",
            streetAddress = "123 Main St",
            countryCodeAlpha2 = "NL",
            locality = "Amsterdam",
            postalCode = "1072 AE",
        )

        val request = SEPADirectDebitRequest(
            accountHolderName = "John Doe",
            customerId = "1234",
            iban = "FR7618106000321234566666608",
            mandateType = SEPADirectDebitMandateType.ONE_OFF,
            billingAddress = billingAddress,
        )

        sepaDirectDebitClient.createPaymentAuthRequest(request) { paymentAuthRequest ->
            when (paymentAuthRequest) {
                is SEPADirectDebitPaymentAuthRequest.ReadyToLaunch -> {
                    val pendingRequest = sepaDirectDebitLauncher.launch(this, paymentAuthRequest)
                    when (pendingRequest) {
                        is SEPADirectDebitPendingRequest.Started -> {
                            // store pendingRequest
                        }

                        is SEPADirectDebitPendingRequest.Failure -> {
                            // handle error
                        }
                    }
                }

                is SEPADirectDebitPaymentAuthRequest.LaunchNotRequired -> {
                    // send paymentAuthRequest.nonce.string to server and create a transaction
                }

                is SEPADirectDebitPaymentAuthRequest.Failure -> {
                    // handle error
                }
            }
        }
    }
}

Next Page: Server-side