# Authorizing a Payment This guide covers additional authorization scenarios beyond the basic example in [Getting Started](/docs/developer/sdk/getting-started/quickstart), including B2B buyers, SEPA Direct Debit, delivery information, device data, sales-channel settings, and CCD2 compliance. ## Authorize a B2B payment with SEPA Direct Debit The following example demonstrates how to authorize a B2B payment using SEPA Direct Debit (`PAY_NOW` / `SEPA_DIRECT_DEBIT`). In addition to the standard authorization fields, the request includes: - **Company information:** The buyer's company details instead of personal buyer information. - **Bank account details:** The account holder's name and IBAN required for SEPA Direct Debit. - **Delivery information:** A delivery address different from the billing address. - **Device information:** The buyer's device information, typically required for online orders. See [Device fingerprinting](/docs/developer/device_fingerprinting/device_fingerprinting) for details. - **Sales channel:** `WEBSHOP` to identify the transaction as an online purchase. ```java Java import com.ratepay.sdk.AuthorizeOutcome; import com.ratepay.sdk.model.api.payment.*; import java.math.BigDecimal; import java.util.List; import java.util.UUID; PaymentMethod paymentMethod = new PaymentMethod(PaymentOption.PAY_NOW, TransferType.SEPA_DIRECT_DEBIT); SepaDirectDebitPaymentDetails paymentDetails = new SepaDirectDebitPaymentDetails( new DebitBankAccount("DE89370400440532013000", "Acme Trading GmbH", null) // iban, owner, bic ); Buyer buyer = new Buyer( new Address("Berlin", "DE", "Torstraße", "10119", null, "1"), // city, countryCode, street, zipCode, streetAddition, streetNumber new Contact("finance@acme-trading.example", "+49 30 9876543"), new Company("Acme Trading GmbH", "Max", "Mustermann", "DE123456789"), // company is mutually exclusive with person, as this is a B2B buyer null, // language null, // person null // shopBuyerId ); Delivery delivery = new Delivery( new Address("Berlin", "DE", "Lagerstraße", "12099", null, "5"), // address, the one delivery type set "Acme Trading GmbH", // company, recipient at the delivery address null, null, null, // firstName, fullName, inStoreCollect null, null, null // lastName, pickUpBox, pickUpShop ); Device device = new Device( null, null, null, null, null, null, // browser, fingerPrint, geoLocation, httpForwardedIpAddress, risk, screen "203.0.113.42", // sourceIpAddress, mandatory for online orders null // token ); Options options = new Options(SalesChannel.WEBSHOP); ShopBasket basket = new ShopBasket( new BigDecimal("249.00"), // grossAmount List.of( new Item( new BigDecimal("249.00"), "Ergonomic Office Chair", BigDecimal.ONE, new BigDecimal("19"), // grossUnitPrice, name, quantity, taxRate "SKU-2050", null, null, null, null, null, null, null, null ) ), "INTEGRATION_TE_DACH", // partnerShopId null, null, UUID.randomUUID().toString(), null // vats, shopMerchantId, shopTransactionId, specialItems ); AuthorizationRequest request = new AuthorizationRequest( buyer, "EUR", paymentMethod, List.of(basket), null, // authorizationExpires null, // complianceDetails delivery, device, options, null, // partnerOperationId UUID.randomUUID().toString(), // partnerTransactionId paymentDetails, null // shops ); AuthorizeOutcome outcome = client.authorize(request, null); ``` ```kotlin Kotlin import com.ratepay.sdk.model.api.payment.* import java.math.BigDecimal import java.util.UUID val request = AuthorizationRequest( paymentMethod = PaymentMethod(PaymentOption.PAY_NOW, TransferType.SEPA_DIRECT_DEBIT), currency = "EUR", buyer = Buyer( billingAddress = Address(street = "Torstraße", streetNumber = "1", zipCode = "10119", city = "Berlin", countryCode = "DE"), contact = Contact(email = "finance@acme-trading.example", phone = "+49 30 9876543"), company = Company(name = "Acme Trading GmbH", firstName = "Max", lastName = "Mustermann", vatId = "DE123456789"), ), shopBaskets = listOf( ShopBasket( partnerShopId = "INTEGRATION_TE_DACH", grossAmount = BigDecimal("249.00"), items = listOf( Item( grossUnitPrice = BigDecimal("249.00"), name = "Ergonomic Office Chair", taxRate = BigDecimal("19"), quantity = BigDecimal.ONE, articleNumber = "SKU-2050", ), ), vats = null, shopTransactionId = UUID.randomUUID().toString(), ), ), options = Options(salesChannel = SalesChannel.WEBSHOP), delivery = Delivery( company = "Acme Trading GmbH", address = Address(street = "Lagerstraße", streetNumber = "5", zipCode = "12099", city = "Berlin", countryCode = "DE"), ), device = Device(sourceIpAddress = "203.0.113.42"), partnerTransactionId = UUID.randomUUID().toString(), paymentDetails = SepaDirectDebitPaymentDetails( debitBankAccount = DebitBankAccount(owner = "Acme Trading GmbH", iban = "DE89370400440532013000"), ), ) val outcome = client.authorize(request) ``` The `authorize()` method returns a typed `AuthorizeOutcome`. See [Authorizing and capturing a payment](/docs/developer/sdk/getting-started/quickstart) for instructions on handling accepted, declined, and OTP-required outcomes. ## Authorize with a CCD2 attestation token For authorizations that require a Consumer Credit Directive II (CCD2) attestation token, use the `authorize(request, attestationToken, idempotencyKey)` method. The attestation token is obtained through `generateSecci()`. **Important:** The SDK sets the supplied token in `request.complianceDetails.attestationToken`, replacing any existing `complianceDetails` on the request. ## Java and Kotlin conventions When constructing authorization requests: - **Java:** Request models use positional constructors. Provide arguments in the declared order, as arguments of the same type may compile even when placed incorrectly. Pass `null` for optional fields that are not used. - **Kotlin:** Use named arguments to improve readability. When mocking overloaded `authorize()` methods, explicitly name the idempotency key argument (for example, `authorize(any(), idempotencyKey = isNull())`) to avoid overload ambiguity. ## Error handling The SDK distinguishes between business declines and API or network errors. - **Business declines:** Returned as `AuthorizeOutcome.Declined`, allowing you to handle declined payments without catching exceptions. - **Validation and API errors:** Thrown as exceptions, including `RatepaySdkValidationException`, `RatepayAuthException`, `RatepayValidationException`, `RatepayNotFoundException`, `RatepayLegalException`, and `RatepayNetworkException`. For details on exception types, HTTP status codes, and error handling, see [Exception hierarchy](/docs/developer/sdk/errors-and-resilience/exception-hierarchy). ## Next steps - [Completing OTP verification](/docs/developer/sdk/guides/completing-otp-verification) when authorization returns `AuthorizeOutcome.OtpRequired`. - [Capturing](/docs/developer/sdk/guides/capturing-a-transaction) an accepted authorization. - [Increase the amount of an existing authorization](/docs/developer/sdk/guides/incremental-authorization).