# Save Australia BECS Direct Debit details for future payments Use the Setup Intents API to save payment method details for future Australia BECS Direct Debit payments. # iOS Use STPAUBECSFormView, Stripe’s pre-built BECS payment details collection UI, to create a payment form that lets you securely collect bank details without handling sensitive customer data. You can use the [Setup Intents API](https://docs.stripe.com/payments/setup-intents.md) to collect BECS Direct Debit payment method details in advance, and determine the final amount or payment date later. Use it to: - Save payment methods to a wallet to streamline future purchases - Collect surcharges after fulfilling a service - [Start a free trial for a subscription](https://docs.stripe.com/billing/subscriptions/trials.md) ## 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 iOS SDK](https://github.com/stripe/stripe-ios) is open source, [fully documented](https://stripe.dev/stripe-ios/index.html), and compatible with apps supporting iOS 13 or above. #### Swift Package Manager To install the SDK, follow these steps: 1. In Xcode, select **File** > **Add Package Dependencies…** and enter `https://github.com/stripe/stripe-ios-spm` as the repository URL. 2. Select the latest version number from our [releases page](https://github.com/stripe/stripe-ios/releases). 3. Add the **StripePaymentsUI** product to the [target of your app](https://developer.apple.com/documentation/swift_packages/adding_package_dependencies_to_your_app). #### CocoaPods 1. If you haven’t already, install the latest version of [CocoaPods](https://guides.cocoapods.org/using/getting-started.html). 2. If you don’t have an existing [Podfile](https://guides.cocoapods.org/syntax/podfile.html), run the following command to create one: ```bash pod init ``` 3. Add this line to your `Podfile`: ```podfile pod 'StripePaymentsUI' ``` 4. Run the following command: ```bash pod install ``` 5. Don’t forget to use the `.xcworkspace` file to open your project in Xcode, instead of the `.xcodeproj` file, from here on out. 6. In the future, to update to the latest version of the SDK, run: ```bash pod update StripePaymentsUI ``` #### Carthage 1. If you haven’t already, install the latest version of [Carthage](https://github.com/Carthage/Carthage#installing-carthage). 2. Add this line to your `Cartfile`: ```cartfile github "stripe/stripe-ios" ``` 3. Follow the [Carthage installation instructions](https://github.com/Carthage/Carthage#if-youre-building-for-ios-tvos-or-watchos). Make sure to embed all of the required frameworks listed [here](https://github.com/stripe/stripe-ios/tree/master/StripePaymentsUI/README.md#manual-linking). 4. In the future, to update to the latest version of the SDK, run the following command: ```bash carthage update stripe-ios --platform ios ``` #### Manual Framework 1. Head to our [GitHub releases page](https://github.com/stripe/stripe-ios/releases/latest) and download and unzip **Stripe.xcframework.zip**. 2. Drag **StripePaymentsUI.xcframework** to the **Embedded Binaries** section of the **General** settings in your Xcode project. Make sure to select **Copy items if needed**. 3. Repeat step 2 for all required frameworks listed [here](https://github.com/stripe/stripe-ios/tree/master/StripePaymentsUI/README.md#manual-linking). 4. In the future, to update to the latest version of our SDK, repeat steps 1–3. > For details on the latest SDK release and past versions, see the [Releases](https://github.com/stripe/stripe-ios/releases) page on GitHub. To receive notifications when a new release is published, [watch releases](https://help.github.com/en/articles/watching-and-unwatching-releases-for-a-repository#watching-releases-for-a-repository) for the repository. Configure the SDK with your Stripe [publishable key](https://dashboard.stripe.com/test/apikeys) on app start. This enables your app to make requests to the Stripe API. #### Swift ```swift import UIKitimportStripePaymentsUI @main class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {StripeAPI.defaultPublishableKey = "<>" // do any other necessary launch configuration return true } } ``` > 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. ## Create or retrieve a customer [Server-side] To reuse a BECS Direct Debit account for future payments, attach it to an object that represents your Customer. > #### Use the Accounts v2 API to represent customers > > The Accounts v2 API is generally available for Connect users, and in public preview for other Stripe users. If you’re part of the Accounts v2 preview, you need to specify a [preview version](https://docs.stripe.com/api-v2-overview.md#sdk-and-api-versioning) in your code. > > To join the Accounts v2 preview, go to [Account previews and features](https://dashboard.stripe.com/settings/previews) in your Dashboard and enable **Reusable payment methods for Global Payouts**. > > For most use cases, we recommend [modelling your customers as customer-configured Account objects](https://docs.stripe.com/accounts-v2/use-accounts-as-customers.md) instead of using [Customer](https://docs.stripe.com/api/customers.md) objects. Create a customer-configured [Account](https://docs.stripe.com/api/v2/core/accounts/create.md#v2_create_accounts-configuration-customer) or [Customer](https://docs.stripe.com/api/customers/create.md) when your customer creates an account with your business or when saving a payment method. Associate the object’s ID with your own internal representation of a customer. Create a new customer or retrieve an existing one to associate with this payment. #### Accounts v2 ```curl curl -X POST https://api.stripe.com/v2/core/accounts \ -H "Authorization: Bearer <>" \ -H "Stripe-Version: 2026-06-24.preview" \ --json '{ "contact_email": "jenny.rosen@example.com", "display_name": "Jenny Rosen", "configuration": { "customer": {} }, "include": [ "configuration.customer" ] }' ``` #### Customers v1 ```curl curl https://api.stripe.com/v1/customers \ -u "<>:" \ -d "name=Jenny Rosen" \ --data-urlencode "email=jenny.rosen@example.com" ``` ## Collect payment method details and mandate acknowledgment [Client-side] You can securely collect BECS Debit payment information with [STPAUBECSFormView](https://stripe.dev/stripe-ios/stripe-payments-ui/Classes/STPAUBECSDebitFormView.html), a drop-in UI component provided by the SDK. `STPAUBECSFormView​` provides a UI for customers to enter their name, email address, BSB number, and account number – in addition to displaying the [BECS Direct Debit Terms](https://stripe.com/au-becs/legal). Create an instance of `STPAUBECSFormView​` configured with your company name and set up a delegate for the SDK to notify after the customer enters the required details to create an instance of `STPPaymentMethodParams`​. You can also customize `STPAUBECSFormView​` to match the look and feel of your app by providing values to `STPAUBECSFormView​'s` public properties. #### Swift ```swift import UIKit import StripePaymentsUI class CheckoutViewController: UIViewController { private var becsFormView = STPAUBECSDebitFormView(companyName: "Example Company Inc.") private let saveButton = UIButton() private var setupIntentClientSecret: String? override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .secondarySystemBackground saveButton.layer.cornerRadius = 5 saveButton.contentEdgeInsets = UIEdgeInsets(top: 4, left: 8, bottom: 4, right: 8) saveButton.backgroundColor = .systemGray3 saveButton.titleLabel?.font = UIFont.systemFont(ofSize: 18) saveButton.setTitle("Save", for: .normal) saveButton.addTarget(self, action: #selector(save), for: .touchUpInside) saveButton.isEnabled = false saveButton.translatesAutoresizingMaskIntoConstraints = false view.addSubview(saveButton) becsFormView.becsDebitFormDelegate = self becsFormView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(becsFormView) NSLayoutConstraint.activate([ becsFormView.leadingAnchor.constraint(equalTo: view.leadingAnchor), view.trailingAnchor.constraint(equalTo: becsFormView.trailingAnchor), becsFormView.topAnchor.constraint(equalToSystemSpacingBelow: view.safeAreaLayoutGuide.topAnchor, multiplier: 2), saveButton.centerXAnchor.constraint(equalTo: view.centerXAnchor), saveButton.topAnchor.constraint(equalToSystemSpacingBelow: becsFormView.bottomAnchor, multiplier: 2), ]) } @objc func save() { // ... } } extension CheckoutViewController: STPAUBECSDebitFormViewDelegate { func auBECSDebitForm(_ form: STPAUBECSDebitFormView, didChangeToStateComplete complete: Bool) { saveButton.isEnabled = complete saveButton.backgroundColor = complete ? .systemBlue : .systemGray3 } } ``` ## Create a SetupIntent [Server-side] A [SetupIntent](https://docs.stripe.com/api/setup_intents.md) is an object that represents your intent to set up a customer’s payment method for future payments. The `SetupIntent` will track the steps of this set-up process. For BECS Direct Debit, this includes collecting a mandate from the customer and tracking its validity throughout its lifecycle. Create a [SetupIntent](https://docs.stripe.com/api/setup_intents.md) on your server and specify the ID of the customer-configured [Account](https://docs.stripe.com/api/v2/core/accounts/object.md#v2_account_object-id) or [Customer](https://docs.stripe.com/api/customers/object.md#customer_object-id) object. [Enable the payment method](https://dashboard.stripe.com/settings/payment_methods) in your Dashboard. Stripe displays eligible payment methods automatically. #### Accounts v2 #### curl ```bash curl https://api.stripe.com/v1/setup_intents \ -u <>: \ -d "customer_account"="{{CUSTOMER_ACCOUNT_ID}}" \ -d "automatic_payment_methods[enabled]"="true" ``` #### Customers v1 #### curl ```bash curl https://api.stripe.com/v1/setup_intents \ -u <>: \ -d "customer"="{{CUSTOMER_ID}}" \ -d "automatic_payment_methods[enabled]"="true" ``` After creating a `SetupIntent` on your server, you can associate the `SetupIntent` ID with the current session’s customer in your application’s data model. Doing so allows you to retrieve the information after you’ve successfully collected a payment method. The returned `SetupIntent` object contains a `client_secret` property. Pass the client secret to the client-side application to continue with the setup process. ## Submit the payment method details to Stripe [Client-side] After the user enters their payment details, confirm the `SetupIntent` to complete saving the debit information. First, assemble a STPSetupIntentConfirmParams object with: 1. The [STPAUBECSFormView’s](https://stripe.dev/stripe-ios/stripe-payments-ui/Classes/STPAUBECSDebitFormView.html) `paymentMethodParams` property 2. The `SetupIntent` client secret from your server Rather than sending the entire `SetupIntent` object to the client, use its [client secret](https://docs.stripe.com/api/setup_intents/object.md#setup_intent_object-client_secret) from [step 4](https://docs.stripe.com/payments/au-becs-debit/set-up-payment.md#ios-create-setup-intent). This is different from your API keys that authenticate Stripe API requests. The client secret should still be handled carefully because it can complete the setup. Don’t log it, embed it in URLs, or expose it to anyone but the customer. Next, complete the payment by calling the [STPPaymentHandler confirmSetupIntent](https://stripe.dev/stripe-ios/stripe-payments/Classes/STPPaymentHandler.html#/c:objc\(cs\)STPPaymentHandler\(im\)confirmSetupIntent:withAuthenticationContext:completion:) method. Because [customer](https://docs.stripe.com/api/setup_intents/create.md#create_setup_intent-customer) was set, the *PaymentMethod* (PaymentMethods represent your customer's payment instruments, used with the Payment Intents or Setup Intents APIs) will be attached to the provided *Customer* (Customer objects represent customers of your business. They let you reuse payment methods and give you the ability to track multiple payments) object after a successful setup. This allows you to use the stored PaymentMethod to collect future payments without prompting the customer for payment method details. #### Swift ```swift import UIKit import StripePaymentsUI class CheckoutViewController: UIViewController { // ... @objc func save() { guard let setupIntentClientSecret = setupIntentClientSecret, let paymentMethodParams = becsFormView.paymentMethodParams else { return; } let setupIntentParams = STPSetupIntentConfirmParams(clientSecret: setupIntentClientSecret) setupIntentParams.paymentMethodParams = paymentMethodParams STPPaymentHandler.shared().confirmSetupIntent(withParams: setupIntentParams, authenticationContext: self) { (handlerStatus, setupIntent, error) in switch (handlerStatus) { case .failed: // Setup failed break case .canceled: // Setup canceled break case .succeeded: // Setup succeeded break @unknown default: fatalError() break } } } } extension CheckoutViewController: STPAuthenticationContext { func authenticationPresentingViewController() -> UIViewController { return self } } ``` After confirming the `SetupIntent`​, share the [mandate URL](https://docs.stripe.com/api/mandates/object.md#mandate_object-payment_method_details-au_becs_debit-url) from the [Mandate object](https://docs.stripe.com/api/mandates.md) with your customer. We also recommend including the following details when you confirm their mandate has been established: - An explicit confirmation message that indicates a Direct Debit arrangement has been set up - The [business name](https://docs.stripe.com/payments/au-becs-debit/accept-a-payment.md) that will appear on the customer’s bank statement whenever their account gets debited - The payment amount and schedule (if applicable) - A link to the generated DDR mandate URL ​​You can access the `Mandate​` object’s ID from the `mandate` on the [SetupIntent object](https://docs.stripe.com/api/setup_intents/object.md#setup_intent_object-mandate) (included with the `setup_intent.succeeded` event sent after confirmation) or you can [retrieve it through the API](https://docs.stripe.com/api/setup_intents/retrieve.md). ## Test the integration You can test your form using the test BSB number `000000` and one of the test account numbers below with your [STPPaymentHandler confirmSetupIntent](https://stripe.dev/stripe-ios/stripe-payments/Classes/STPPaymentHandler.html#/c:objc\(cs\)STPPaymentHandler\(im\)confirmSetupIntent:withAuthenticationContext:completion:) method call. | BSB Number | Account number | Token | Description | | ---------- | -------------- | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `000000` | `000123456` | `pm_auBecsDebit_success` | The PaymentIntent created with the resulting PaymentMethod transitions from `processing` to `succeeded`. The mandate status remains `active`. | | `000000` | `900123456` | `pm_auBecsDebit_successDelayed` | The PaymentIntent created with the resulting PaymentMethod transitions from `processing` to `succeeded` (with a three-minute delay). The mandate status remains `active`. | | `000000` | `111111113` | `pm_auBecsDebit_accountClosed` | The PaymentIntent created with the resulting PaymentMethod transitions from `processing` to `requires_payment_method` with an `account_closed` failure code. The mandate status becomes `inactive` at that point. | | `000000` | `111111116` | `pm_auBecsDebit_noAccount` | The PaymentIntent created with the resulting PaymentMethod transitions from `processing` to `requires_payment_method` with a `no_account` failure code. The mandate status becomes `inactive` at that point. | | `000000` | `222222227` | `pm_auBecsDebit_referToCustomer` | The PaymentIntent created with the resulting PaymentMethod transitions from `processing` to `requires_payment_method` with a `refer_to_customer` failure code. The mandate status remains `active`. | | `000000` | `922222227` | `pm_auBecsDebit_referToCustomerDelayed` | The PaymentIntent created with the resulting PaymentMethod transitions from `processing` to `requires_payment_method` with a `refer_to_customer` failure code (with a three-minute delay). The mandate status remains `active`. | | `000000` | `333333335` | `pm_auBecsDebit_debitNotAuthorized` | The PaymentIntent created with the resulting PaymentMethod transitions from `processing` to `requires_payment_method` with a `debit_not_authorized` failure code. The mandate status becomes `inactive` at that point. | | `000000` | `666666660` | `pm_auBecsDebit_dispute` | The PaymentIntent created with the resulting PaymentMethod transitions from `processing` to `succeeded`, but a dispute is immediately created. | | `000000` | `343434343` | `pm_auBecsDebit_exceedsWeeklyLimit` | The PaymentIntent that was created with the resulting PaymentMethod fails with a `charge_exceeds_source_limit` error due to the payment amount causing the account to exceed its weekly payment volume limit. | | `000000` | `121212121` | `pm_auBecsDebit_exceedsTransactionLimit` | The PaymentIntent that was created with the resulting PaymentMethod fails with a `charge_exceeds_transaction_limit` error due to the payment amount exceeding the account’s transaction volume limit. | ## See also - [Accept an Australia BECS Direct Debit payment](https://docs.stripe.com/payments/au-becs-debit/accept-a-payment.md) - [Connect payments](https://docs.stripe.com/connect/charges.md)