# Accept a Multibanco payment

Learn how to accept the Multibanco payment method.

# Android


> We recommend that you follow the [Accept a payment](https://docs.stripe.com/payments/accept-a-payment.md) guide unless you need to use manual server-side confirmation, or your integration requires presenting payment methods separately. If you’ve already integrated with Elements, see the [Payment Element migration guide](https://docs.stripe.com/payments/payment-element/migration.md).

Multibanco is a voucher-based payment method in Portugal. If your business is based in Europe or the United States, you can accept Multibanco payments from customers in Portugal using the [Payment Intents API](https://docs.stripe.com/payments/payment-intents.md).

To complete a transaction, customers receive a voucher that includes a Multibanco entity and reference numbers. Customers use these voucher details to make a payment outside your checkout flow through online banking or from an ATM.

Payment confirmation might be delayed by several days due to the initiation of a bank transfer when a customer pays for a Multibanco voucher. Bank transfers can encounter delays, particularly over weekends, contributing to the delay in payment confirmation.

## Set up Stripe [Server-side] [Client-side]

First, you need a Stripe account. [Register now](https://dashboard.stripe.com/register).

### Server-side 

This integration requires endpoints on your server that talk to the Stripe API. Use the official libraries for access to the Stripe API from your server:

#### Ruby

```bash
# Available as a gem
sudo gem install stripe
```

```ruby
# If you use bundler, you can add this line to your Gemfile
gem 'stripe'
```

### Client-side 

The [Stripe Android SDK](https://github.com/stripe/stripe-android) is open source and [fully documented](https://stripe.dev/stripe-android/).

To install the SDK, add `stripe-android` to the `dependencies` block of your [app/build.gradle](https://developer.android.com/studio/build/dependencies) file:

#### Kotlin

```kotlin
plugins {
    id("com.android.application")
}

android { ... }

dependencies {
  // ...

  // Stripe Android SDK
  implementation("com.stripe:stripe-android:23.18.0")
  // Include the financial connections SDK to support US bank account as a payment method
  implementation("com.stripe:financial-connections:23.18.0")
}
```

> For details on the latest SDK release and past versions, see the [Releases](https://github.com/stripe/stripe-android/releases) page on GitHub. To receive notifications when a new release is published, [watch releases for the repository](https://docs.github.com/en/github/managing-subscriptions-and-notifications-on-github/configuring-notifications#configuring-your-watch-settings-for-an-individual-repository).

Configure the SDK with your Stripe [publishable key](https://dashboard.stripe.com/apikeys) so that it can make requests to the Stripe API, such as in your `Application` subclass:

#### Kotlin

```kotlin
import com.stripe.android.PaymentConfiguration

class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        PaymentConfiguration.init(
            applicationContext,
            "<<YOUR_PUBLISHABLE_KEY>>"
        )
    }
}
```

> Use your [test keys](https://docs.stripe.com/keys.md#obtain-api-keys) while you test and develop, and your [live mode](https://docs.stripe.com/keys.md#test-live-modes) keys when you publish your app.

Stripe samples also use [OkHttp](https://github.com/square/okhttp) and [GSON](https://github.com/google/gson) to make HTTP requests to a server.

## Create a PaymentIntent [Server-side] [Client-side]

Stripe uses a [PaymentIntent](https://docs.stripe.com/api/payment_intents/object.md) object to represent your intent to collect payment from a customer, tracking state changes from Multibanco voucher creation to payment completion.

### Server-side 

Create a PaymentIntent on your server with an amount and the `eur` currency (Multibanco doesn’t support other currencies). [Enable the payment method](https://dashboard.stripe.com/settings/payment_methods) in your Dashboard. Stripe displays eligible payment methods to customers automatically.

```curl
curl https://api.stripe.com/v1/payment_intents \
  -u "<<YOUR_SECRET_KEY>>:" \
  -d amount=1099 \
  -d currency=eur \
  -d "automatic_payment_methods[enabled]=true"
```

The returned PaymentIntent includes a *client secret* (The client secret is a unique key returned from Stripe as part of a PaymentIntent. This key lets the client access important fields from the PaymentIntent (status, amount, currency) while hiding sensitive ones (metadata, customer)), that you’ll use to *confirm* (Confirming an intent indicates that the customer intends to use the current or provided payment method. Upon confirmation, the intent attempts to initiate the portions of the flow that have real-world side effects) the PaymentIntent. Send the client secret back to the client so you can use it in the next step.

### Client-side 

On the client, request a PaymentIntent from your server and store its client secret.

#### Kotlin

```kotlin
class CheckoutActivity : AppCompatActivity() {

  private lateinit var paymentIntentClientSecret: String

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

  private fun startCheckout() {
      // Request a PaymentIntent from your server and store its client secret in paymentIntentClientSecret
      // Click View full sample to see a complete implementation
  }
}
```

## Collect payment method details [Client-side]

In your app, collect the following required billing details from the customer. Create a [PaymentMethodCreateParams](https://stripe.dev/stripe-android/payments-core/com.stripe.android.model/-payment-method-create-params/index.html) with the billing details.

| Field   | Value                                   |
| ------- | --------------------------------------- |
| `email` | The full email address of the customer. |

#### Kotlin

```kotlin
val billingDetails = PaymentMethod.BillingDetails(email = "jenny@example.com")
val paymentMethodCreateParams = PaymentMethodCreateParams.createMultibanco(billingDetails)
```

## Submit the payment to Stripe [Client-side]

Submit the customer’s billing details by calling [PaymentLauncher confirm](https://stripe.dev/stripe-android/payments-core/com.stripe.android.payments.paymentlauncher/-payment-launcher/index.html#74063765%2FFunctions%2F-1622557690) with the [client secret](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-client_secret) of the PaymentIntent object that you created. This presents a webview to display the Multibanco voucher. Afterwards, `onPaymentResult` is called with the result of the payment.

#### Kotlin

```kotlin
class MultibancoActivity : AppCompatActivity() {
    // ...
    private lateinit var paymentIntentClientSecret: String
    private val paymentLauncher: PaymentLauncher by lazy {
        val paymentConfiguration = PaymentConfiguration.getInstance(applicationContext)
        PaymentLauncher.Companion.create(
            this,
            paymentConfiguration.publishableKey,
            paymentConfiguration.stripeAccountId,
            ::onPaymentResult
        )
    }

    private fun startCheckout() {
        // ...
        val confirmParams = ConfirmPaymentIntentParams
                .createWithPaymentMethodCreateParams(
                  paymentMethodCreateParams = paymentMethodCreateParams,
                  clientSecret = paymentIntentClientSecret
                )
        paymentLauncher.confirm(confirmParams)
    }

    private fun onPaymentResult(paymentResult: PaymentResult) {
        when (paymentResult) {
            is PaymentResult.Completed -> {
                // The Multibanco voucher was displayed successfully. The customer can now pay the Multibanco voucher
            }
            is PaymentResult.Canceled -> {
                // Handle cancelation
            }
            is PaymentResult.Failed -> {
                // Handle failure
            }
        }
    }
}
```

Stripe sends a [payment_intent.requires_action](https://docs.stripe.com/api/events/types.md#event_types-payment_intent.requires_action) event when a Multibanco voucher is created successfully. If you need to send an email with the voucher’s payment instructions link, you can locate the `hosted_voucher_url` at [payment_intent.next_action.multibanco_display_details.hosted_voucher_url](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-next_action-multibanco_display_details-hosted_voucher_url).

## Optional: Send automated payment instruction emails

You can enable Multibanco payment instruction emails on the [Email Settings](https://dashboard.stripe.com/settings/emails) page in the Dashboard. After you enable it, Stripe automatically sends payment instruction emails upon PaymentIntent confirmation. The emails contain the Multibanco voucher instructions and a link to the Stripe-hosted voucher page.

> In testing environments, instruction emails are only sent to email addresses linked to the Stripe account.

## Optional: Customize voucher appearance

Customize your customer-facing UIs in the [Branding Settings](https://dashboard.stripe.com/account/branding) page.

You can apply the following Branding settings to the Stripe-hosted voucher page:

- **Icon**: Your brand image and public business name
- **Logo**: Your brand image
- **Accent color**: The color of the Print button
- **Brand color**: The background color

## Handle post-payment events [Server-side]

Multibanco is a [delayed notification](https://docs.stripe.com/payments/payment-methods.md#payment-notification) payment method. A customer pays for a Multibanco voucher outside your checkout flow through online banking or from an ATM.

After a Multibanco payment completes, Stripe sends a [payment_intent.succeeded](https://docs.stripe.com/api/events/types.md#event_types-payment_intent.succeeded) event. Use the Dashboard or build a *webhook* (A webhook is a real-time push notification sent to your application as a JSON payload through HTTPS requests) handler to receive these events and run actions, such as sending an order confirmation email to your customer, logging the sale in a database, or initiating a shipping workflow.

Learn about Multibanco [expiration](https://docs.stripe.com/payments/multibanco/accept-a-payment.md#expiration).

| Event                            | Description                                                | Next steps                                                                                  |
| -------------------------------- | ---------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| `payment_intent.requires_action` | The Multibanco voucher is created successfully.            | Wait for the customer to pay for the Multibanco voucher.                                    |
| `payment_intent.processing`      | The customer can no longer pay for the Multibanco voucher. | Wait for the initiated payment to succeed or fail.                                          |
| `payment_intent.succeeded`       | The customer paid for the Multibanco voucher.              | Fulfill the goods or services that the customer purchased.                                  |
| `payment_intent.payment_failed`  | The customer didn’t pay for the Multibanco voucher.        | Contact the customer through email or push notification and request another payment method. |

### Receive events and run business actions

#### Manually

Use the Stripe Dashboard to view all your Stripe payments, send email receipts, handle payouts, or retry failed payments.

View your [test payments in the Dashboard](https://dashboard.stripe.com/test/payments).

#### Custom Code

Build a webhook handler to listen for events and build custom asynchronous payment flows. Test and debug your webhook integration locally with the Stripe CLI.

Learn how to [build a custom webhook](https://docs.stripe.com/webhooks/handling-payment-events.md#build-your-own-webhook).

## Test the integration

In a *sandbox* (A sandbox is an isolated test environment that allows you to test Stripe functionality in your account without affecting your live integration. Use sandboxes to safely experiment with new features and changes), set [PaymentMethod.BillingDetails#email](https://stripe.dev/stripe-android/payments-core/com.stripe.android.model/-payment-method/-billing-details/index.html) to the following values when you call [Stripe\# confirmPayment()](https://stripe.dev/stripe-android/payments-core/com.stripe.android/-stripe/confirm-payment.html) to test different scenarios.

| Email                                          | Description                                                                                                                                                                                                                                                                                                    |
| ---------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `{any_prefix}@{any_domain}`                    | Simulates a Multibanco voucher that a customer pays. The `payment_intent.succeeded` webhook arrives after about 3 minutes.

  Example: jenny@example.com                                                                                                                                                       |
| `{any_prefix}succeed_immediately@{any_domain}` | Simulates a Multibanco voucher that a customer pays immediately. The `payment_intent.succeeded` webhook arrives within several seconds.

  Example: succeed_immediately@example.com                                                                                                                            |
| `{any_prefix}expire_immediately@{any_domain}`  | Simulates a Multibanco voucher that expires immediately. The `payment_intent.payment_failed` webhook arrives within several seconds.

  Example: expire_immediately@example.com                                                                                                                                |
| `{any_prefix}expire_with_delay@{any_domain}`   | Simulates a Multibanco voucher that expires before a customer pays. The `payment_intent.payment_failed` webhook arrives after about 3 minutes.

  Example: expire_with_delay@example.com                                                                                                                       |
| `{any_prefix}fill_never@{any_domain}`          | Simulates a Multibanco voucher that never succeeds. The `payment_intent.payment_failed` webhook arrives after 11 days, which mimics behavior in live mode. Learn about Multibanco [expiration](https://docs.stripe.com/payments/multibanco/accept-a-payment.md#expiration).

  Example: fill_never@example.com |

## Expiration 

Multibanco vouchers expire at the `expires_at` UNIX timestamp in [next_action.multibanco_display_details.expires_at](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-next_action-multibanco_display_details-expires_at), which is 7 days after you create the voucher. Customers can’t pay a Multibanco voucher after it expires. After expiration, the PaymentIntent’s status transitions from `requires_action` to `processing`, and Stripe sends a [payment_intent.processing](https://docs.stripe.com/api/events/types.md#event_types-payment_intent.processing) event.

The PaymentIntent remains in the `processing` status for a maximum buffer period of 4 days to allow for potential completed payment notification delays caused by bank-transfer delays. If the Multibanco payment doesn’t complete within the buffer period, the PaymentIntent’s status transitions to `requires_payment_method` and Stripe sends a [payment_intent.payment_failed](https://docs.stripe.com/api/events/types.md#event_types-payment_intent.payment_failed) event. If you receive the customer’s funds after the buffer period, Stripe automatically initiates a refund process for the mispaid amount.

## Cancelation 

You can cancel Multibanco vouchers using [Cancel a PaymentIntent](https://docs.stripe.com/api/payment_intents/cancel.md). After cancelation, Stripe sends a [payment_intent.canceled](https://docs.stripe.com/api/events/types.md#event_types-payment_intent.canceled) event.

If a customer’s funds are received for a canceled Multibanco voucher, Stripe automatically initiates a refund process for the mispaid amount.

> Canceling a pending payment invalidates the original voucher instructions. When you cancel a pending Multibanco payment, inform your customer.
> 
> When you successfully reconfirm a PaymentIntent in status `requires_action`, Stripe creates new voucher instructions and a new `hosted_voucher_url`. You must provide them to your customer.

## Refunds 

Learn about Multibanco [refunds](https://docs.stripe.com/payments/multibanco.md#refunds).

