Integración con aplicación móvil

Recomendación general

⚠️ No se recomienda el uso de WebView para el proceso de pago. Aunque técnicamente es posible integrar el checkout dentro de un WebView, no es la opción más recomendada.

Se recomienda utilizar browsers reales del sistema, ya que usan el motor nativo, comparten cookies con el browser del dispositivo y mantienen correctamente el contexto del usuario durante redirecciones (3DS, autenticaciones, wallets).

Opción
Android
iOS
Browser externo
Chrome
Safari
Browser in-app
Chrome Custom Tabs
SFSafariViewController

¿Por qué no WebView?

  • Restricciones en acciones del usuario (autoplay, popups, wallets).
  • Limitaciones en redirecciones entre dominios.
  • Comportamientos inconsistentes entre versiones del sistema operativo.
  • Mayor superficie de mantenimiento.

Billeteras digitales en WebView

Las condiciones para usar billeteras dentro de un WebView dependen de la plataforma: en Android, tu app debe habilitar la Payment Request API que usa Google Pay; en iOS, WKWebView tiene restricciones propias para Google Pay y Apple Pay. Si ofreces billeteras en tu app, abre Webcheckout en un browser in-app o externo. Si necesitas mantener el WebView, configura tu app según la plataforma:

Entorno
Google Pay
Apple Pay
Browser in-app o externo
Compatible sin configuración adicional en la app.
Compatible en Safari y SFSafariViewController (iOS).
WebView en Android
Compatible si configuras el WebView y el dispositivo cumple los requisitos. Ver configuración.
Apple no documenta soporte.
WKWebView en iOS
Google documenta una configuración, pero indica que la comprobación de disponibilidad siempre responde false. Ver consideraciones.
Compatible desde iOS 13 si tu app no inyecta JavaScript. Ver consideraciones.

Para Google Pay, la comprobación de disponibilidad y los errores que pueden ocurrir durante el pago se describen en Disponibilidad y errores durante el pago.

Google Pay en WebView Android

Según la guía de Google para Android WebView, el dispositivo del pagador debe tener:

  • Google Play services 25.18.30 o superior.
  • Android System WebView 137 o superior.

Para habilitar Google Pay, realiza estos cambios en tu app:

  1. Agrega la dependencia androidx.webkit en la versión 1.14.0 o superior.
dependencies {
    implementation 'androidx.webkit:webkit:1.14.0'
}
  1. Declara en AndroidManifest.xml las consultas que usa Google Pay.
<queries>
  <intent>
    <action android:name="org.chromium.intent.action.PAY"/>
  </intent>
  <intent>
    <action android:name="org.chromium.intent.action.IS_READY_TO_PAY"/>
  </intent>
  <intent>
    <action android:name="org.chromium.intent.action.UPDATE_PAYMENT_DETAILS"/>
  </intent>
</queries>
  1. Habilita JavaScript y la Payment Request API en el WebView. Si usas el componente CheckoutWebView de la integración con Android, agrega estas líneas junto a la configuración de settings.
import androidx.webkit.WebSettingsCompat
import androidx.webkit.WebViewFeature

settings.javaScriptEnabled = true
if (WebViewFeature.isFeatureSupported(WebViewFeature.PAYMENT_REQUEST)) {
    WebSettingsCompat.setPaymentRequestEnabled(settings, true)
}
  1. Si personalizas el user agent del WebView, agrega al final el texto GOOGLE_PAY_SUPPORTED.
  2. No interceptes solicitudes con shouldInterceptRequest para enviarlas por un cliente HTTP de terceros; Google no soporta esta configuración.
  3. Completa el proceso de publicación de la integración de Google Pay para tu app. Google lo exige para permitir Google Pay dentro del WebView de una aplicación.

Google documenta que, si el dispositivo no cumple los requisitos de versión anteriores, la comprobación de disponibilidad (isReadyToPay) responde false; en ese caso, Webcheckout no muestra el botón. Si falta configuración en la app, el botón puede mostrarse y el flujo fallar al iniciarse, como ocurrió en nuestras pruebas.

Expo / React Native

react-native-webview no expone una propiedad para habilitar la Payment Request API. Aplica los pasos 1 a 3 con código nativo, por ejemplo mediante un config plugin, y ejecuta la app como development build: Expo Go no incluye código nativo personalizado. Si personalizas el user agent, incluye GOOGLE_PAY_SUPPORTED, por ejemplo con applicationNameForUserAgent:

<WebView
  source={{ uri: processUrl }}
  javaScriptEnabled={true}
  domStorageEnabled={true}
  applicationNameForUserAgent="GOOGLE_PAY_SUPPORTED" // Agrega GOOGLE_PAY_SUPPORTED al user agent.
/>

Billeteras en WebView iOS

En iOS, Apple documenta Safari y SFSafariViewController como los contextos compatibles con Apple Pay en la web. Si ofreces billeteras, la opción recomendada es el browser in-app, que en iOS usa SFSafariViewController. Si usas WKWebView, ten en cuenta lo siguiente.

Google Pay

  • Google publica una guía para WKWebView: agrega GOOGLE_PAY_SUPPORTED al user agent e implementa los métodos webView(_:createWebViewWith:for:windowFeatures:) y webViewDidClose(_:) de WKUIDelegate para mostrar y cerrar las ventanas emergentes que abre el flujo de pago.
  • En sus preguntas frecuentes, Google indica que en los WebViews de iOS la verificación isReadyToPay siempre responde false por las restricciones de iOS sobre cookies de terceros. Aun con la configuración anterior, Google Pay puede no estar disponible.

Apple Pay

  • WKWebView admite Apple Pay desde iOS 13, pero lo deshabilita si la app usa APIs de inyección de scripts como WKUserScript o evaluateJavaScript(_:completionHandler:) antes de que la página use Apple Pay. La restricción se reinicia cada vez que navega el frame principal (WebKit).
  • En react-native-webview, habilita la propiedad enableApplePay={true}. Con ella dejan de funcionar injectedJavaScript, injectedJavaScriptBeforeContentLoaded, injectJavaScript, sharedCookiesEnabled y el historial HTML5 (referencia).

Integración con Expo / React Native

Una vez hayas obtenido una sesión de pago de tu servicio de backend, puedes iniciar el proceso de pago en la aplicación móvil. A diferencia de Android nativo, en Expo tienes tres opciones para abrir la processUrl, cada una con distintos niveles de compatibilidad y experiencia de usuario.

Browser in-app (recomendada)

Usa expo-web-browser para abrir Chrome Custom Tabs (Android) o SFSafariViewController (iOS) sin salir de la app. Soporta 3DS y comparte las cookies del sistema.

npx expo install expo-web-browser
import * as WebBrowser from 'expo-web-browser'

const result = await WebBrowser.openBrowserAsync(processUrl)

Browser externo

Abre la URL en el browser por defecto del dispositivo. Usa deep links con tu returnUrl y cancelUrl para que la app sea notificada al finalizar.

import { Linking } from 'react-native'

await Linking.openURL(processUrl)

WebView (no recomendada)

npx expo install react-native-webview
import { WebView } from 'react-native-webview'
;<WebView
  source={{ uri: processUrl }}
  javaScriptEnabled={true} // Requerido para ejecutar los scripts del checkout.
  domStorageEnabled={true} // Mantiene el estado de la sesión entre redirecciones.
  thirdPartyCookiesEnabled={true} // Necesario para 3DS y otras redirecciones de autenticación.
  mediaPlaybackRequiresUserAction={false} //Solo si requieres reproducir video. Permite autoplay de video sin interacción del usuario. En iOS también requiere el atributo `muted` en el video.
  allowsInlineMediaPlayback={true} // Usar junto con `mediaPlaybackRequiresUserAction={false}`.
/>

Si ofreces Google Pay o Apple Pay, revisa la configuración adicional en Billeteras digitales en WebView.

Ejemplo de integración

Antes de integrar en tu app, puedes validar el comportamiento del checkout con las siguientes herramientas. Todas permiten ingresar la URL de la sesión y abrirla en distintos modos de navegación (WebView, browser externo y browser in-app).

El punto de entrada es App.js. La lógica del browser in-app (opción recomendada) está en el modo inapp, que usa WebBrowser.openBrowserAsync.

También está disponible un Snack en Expo para ejecución rápida sin configuración local.


Integración con Android (Kotlin)

Una vez hayas obtenido una sesión de pago de tu servicio de backend, puedes iniciar el proceso de pago en la aplicación móvil. Consulta la recomendación general para elegir el modo de navegación más adecuado.

Si decides usar WebView, puedes cargar la processUrl con el método loadUrl de la clase WebView. Es importante que no olvides permitir tanto el JavaScript como las Cookies para el correcto funcionamiento de la sesión de pago, de lo contrario esta no permitirá avanzar en el proceso.

Si ofreces Google Pay, completa también la configuración de Google Pay en WebView Android.

Configurar la WebView

Estas configuraciones ayudan a optimizar y personalizar la experiencia de navegación dentro del WebView. Es importante que puedas identificar cuál es la URL de retorno y la URL de cancelación para poder cerrar el WebView una vez finalice el proceso de pago.

import android.annotation.SuppressLint
import android.view.ViewGroup
import android.webkit.WebChromeClient
import android.webkit.WebResourceRequest
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.compose.runtime.Composable
import androidx.compose.ui.viewinterop.AndroidView
import com.placetopay.p2pr.utilities.Constants

@SuppressLint("SetJavaScriptEnabled")
@Composable
fun CheckoutWebView(processUrl: String, returnUrl: String, cancelUrl: String, refreshWebView: Boolean, onFinished: () -> Unit) {
    AndroidView(factory = {
        WebView(it).apply {
            layoutParams = ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT
            )
            settings.javaScriptEnabled = true
            settings.domStorageEnabled = true
            clearCache(true)

            CookieManager.getInstance().setAcceptCookie(true)
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                CookieManager.getInstance().setAcceptThirdPartyCookies(this, true)
            }

            webChromeClient = WebChromeClient()
            webViewClient = object : WebViewClient() {
                override fun shouldOverrideUrlLoading(
                    view: WebView?, request: WebResourceRequest?
                ): Boolean {
                    if (request?.url.toString() == returnUrl || request?.url.toString() == cancelUrl)
                        onFinished()
                    return super.shouldOverrideUrlLoading(view, request)
                }
            }
            loadUrl(processUrl)
        }
    }, update = {
        it.loadUrl(processUrl)
        if (refreshWebView) it.reload()
    })
}
Configuración
Descripción
JavaScriptEnabled
Habilita la ejecución de JavaScript en la página web.
DomStorageEnabled
Permite que las páginas web almacenen datos localmente, lo que puede mejorar la velocidad y el rendimiento.
ClearCache
Borra la caché de WebView antes de cargar una nueva URL.
WebChromeClient and WebViewClient
Configura el comportamiento del WebView para eventos como la carga y la interacción con la página.
CookieManager
Permite el uso de cookies en el WebView.

Ejemplo de integración