# Upgrade from Frames for Android Follow this guide to upgrade your Frames for Android integration to Flow for mobile. --- ## Before you start Create a [public key and a secret key](https://www.checkout.com/docs/resources/api-authentication/api-keys.md) from the [Dashboard](https://dashboard.checkout.com), with the following key scopes: - Public key – `payment-sessions:pay` and `vault-tokenization` - Secret key – `payment-sessions` To receive webhooks for the [payment events](https://www.checkout.com/docs/developer-resources/event-notifications/event-types.md#Gateway), [configure your webhook server](https://www.checkout.com/docs/developer-resources/event-notifications/receive-webhooks/configure-your-webhook-server.md). --- ## Remove existing Frames code To prepare for the upgrade to Flow, remove all Frames code from your client-side and server-side integrations. ### Remove Frames dependency `Client side` Remove Frames from the Gradle file of the app. ```java // app gradle file implementation("com.github.checkout:frames-android:") ``` ### Remove Frames initialization `Client side` Remove any Kotlin code where you initialize Frames. For example: ```kotlin val paymentFlowHandler = PaymentFlowHandler() val paymentFormConfig = PaymentFormConfig( publicKey = PUBLIC_KEY, context = context, environment = Environment.Production, paymentFlowHandler = paymentFlowHandler, style = PaymentFormStyle(), ) val paymentFormMediator = PaymentFormMediator(paymentFormConfig()) // in Activity paymentFormMediator.setActivityContent(activity) // in Compose paymentFormMediator.PaymentForm() ``` ### Remove payment logic `Server side` Remove all server-side API calls to the following endpoints: **Production** `POST` `https://api.checkout.com/payments` **Sandbox** `POST` `https://api.sandbox.checkout.com/payments` --- ## Create a Flow Payment Session `Server side` Update your server to create a `PaymentSession` for the Flow integration: ```javascript const createPaymentSession = async (req, res) => { const response = await fetch("https://{prefix}.api.checkout.com/payment-sessions", { method: "POST", headers: { Authorization: `Bearer ${secretKey}`, "Content-Type": "application/json", }, body: JSON.stringify({ amount: 1000, currency: "GBP", reference: "ORD-123A", display_name: "Online Shop", billing: { address: { country: "GB" }, }, customer: { name: "Jia Tsang", email: "jia.tsang@example.com", }, success_url: "https://example.com/payments/success", failure_url: "https://example.com/payments/failure", }), }); const paymentSession = await response.json(); res.json(paymentSession); }; ``` --- ## Initialize and mount Flow `Client side` ### Add Flow dependency Include the Flow dependency in your app: ```kotlin // app gradle file implementation("com.checkout:checkout-android-components:") // project gradle file repositories { mavenCentral() // Include the required Maven repositories to resolve Risk SDK dependencies: maven { url = uri("https://jitpack.io") } maven { url = uri("https://maven.fpregistry.io/releases") } ``` ### Initialize Flow Configure Flow with your public key and the payment session data returned from the server: ```kotlin val config = CheckoutComponentConfiguration( context = context, paymentSession = PaymentSessionResponse( id = paymentSessionId, paymentSessionToken = paymentSessionToken, paymentSessionSecret = paymentSessionSecret, ), publicKey = PUBLIC_KEY, environment = Environment.PRODUCTION, ) // Create CheckoutComponents CoroutineScope(Dispatchers.IO).launch { try { val checkoutComponents = CheckoutComponentsFactory(config).create() } catch (checkoutError: CheckoutError) { handleError(checkoutError) } } ``` ### Render Flow Use `CheckoutComponents` to create a `flow` component that displays a list of all available payment methods for the current payment session: ```kotlin val flow = checkoutComponents.create(ComponentName.Flow) ``` Add the Flow component to a container View or render Flow in a Composable function: ```kotlin // in Compose if (flow.isAvailable) { flow.Render() } // in View if (flow.isAvailable) { flow.provideView(containerView) } ``` --- ## Handle payment responses You can use Flow to handle payment methods that require a redirect (asynchronous payments) and those that do not (synchronous payments). ### Asynchronous payments Depending on the payment outcome, customers are redirected to the `success_url` or `failure_url` you specified when you created the `PaymentSession`. We send a webhook to your server notifying you of changes to the payment's status. Wait for the webhook callback before you start your order fulfillment process. For payments submitted with Flow, the `PaymentSession` ID is returned in the webhook payload's `data.metadata.cko_payment_session_id` field. Optionally, you can retrieve the payment result using the callbacks provided by Flow: - `onSuccess` for successful payments - `onError` for unsuccessful payments ### Synchronous payments For payment methods that do not require a redirect, use the `onSuccess` callback to handle payments. You can use this to notify the customer of the payment status. ```kotlin val config = CheckoutComponentConfiguration( context = context, paymentSession = paymentSessionResponse, publicKey = PUBLIC_KEY, environment = Environment.PRODUCTION, componentCallback = ComponentCallback( onSuccess = { component, paymentId -> // Complete order in server side completeOrder(paymentId); } ) ) ``` We send a webhook to your server notifying you of changes to the payment's status. Wait for the webhook callback before you start your order fulfillment process. --- ## Test the Flow integration Use our [test cards](https://www.checkout.com/docs/developer-resources/testing/test-cards.md) to simulate different payment flows, to ensure your integration is set up correctly and behaving as expected. > **Information** > > Ensure that you test each payment method that you plan to offer to your customers. You can check the status of a payment from the _Payments_ > _Processing_ > _All payments_ page in the [Dashboard](https://dashboard.checkout.com). --- ## Upgrade your Google Pay integration You can use Flow for mobile to natively offer Google Pay payments. To upgrade from your Google Pay Frames integration: 1. Contact your account manager and provide your Google Pay Merchant ID. 2. Remove the Google Pay SDK integration from your Gradle files. 3. Remove any Google Pay SDK code from your app. 4. Remove any `GooglePayTokenRequest` related code from your Frames implementation. For Example: ```kotlin val checkoutApiClient = CheckoutApiServiceFactory.create( publicKey = PUBLIC_KEY, environment = Environment.PRODUCTION, context = context, ) val request = GooglePayTokenRequest( tokenJsonPayload = tokenJsonPayload, onSuccess = { tokenDetails -> /* Handle success result */ tokenDetails.token }, onFailure = { errorMessage -> /* Handle failure result */ }, ) checkoutApiClient.createToken(request) ``` 5. Follow the [Flow for mobile instructions](https://www.checkout.com/docs/payments/accept-payments/accept-a-payment-on-your-mobile-app/get-started-with-flow-for-mobile.md#Google_Pay) to accept Google Pay payments. --- ## Next steps **[Customize your Flow for mobile integration](https://www.checkout.com/docs/payments/accept-payments/accept-a-payment-on-your-mobile-app/customize-flow-for-mobile.md)** Learn how to customize your Flow for mobile integration. **[Flow for mobile library reference](https://www.checkout.com/docs/payments/accept-payments/accept-a-payment-on-your-mobile-app/flow-for-mobile-library-reference/android.md)** See the configuration options and error handling steps for Flow for mobile. **[Tokenize credentials](https://www.checkout.com/docs/payments/store-and-manage-credentials/tokenize-credentials.md)** Securely collect and tokenize credentials with Flow for mobile.