> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fintoc.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Integración con WebView

> Referencia para integrar el Widget como un WebView en tu aplicación móvil

## Integración

Para integrar el Widget usando un WebView en iOS y Android, debes usar el siguiente HTML:

```text theme={null}
https://webview.fintoc.com/widget.html
```

La configuración del widget se debe pasar a través de una *querystring* en lugar de usar JavaScript del lado del cliente.

<Info>
  **¿Usas React Native?**

  ¡Revisa nuestra librería de npm [`@fintoc/fintoc-react-native`](https://github.com/fintoc-com/fintoc-react-native) para integrar el WebView a tu aplicación rápidamente!
</Info>

## Cómo funciona

Al incluir el WebView de Fintoc en tu aplicación móvil, necesitas pasar los siguientes *query params* para configurarlo, dependiendo del producto que quieras usar:

```text Text theme={null}
https://webview.fintoc.com/widget.html
  ?public_key=pk_live_00000
  &holder_type=individual
  &product=payments
  &country=cl
  &widget_token=pi_XXXXXX_sec_YYYYYYYY
```

| Parámetro       | Tipo     | Descripción                                                                                                                                                                                                                                                                                                                                                                                                           |
| :-------------- | :------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `public_key`    | `string` | El `public_key` se usa para identificar tu aplicación web o página web dentro de Fintoc. Los Links creados con un `public_key` se asignarán a la organización o usuario que es dueño de dicho `public_key`.<br />Este token determinará si estás usando el sandbox o el entorno de producción. Recuerda que el `public_key` del sandbox empieza con `pk_test_`, mientras que el de producción empieza con `pk_live_`. |
| `holder_type`   | `string` | El parámetro `holder_type` puede ser `business` o `individual`, y determina el tipo de cuenta que se conectará a Fintoc.<br /><br />\* \*Este parámetro no es requerido para el producto Payment Initiation\*\*.                                                                                                                                                                                                      |
| `product`       | `string` | El parámetro `product` puede ser `movements`, `subscriptions`, `invoices` o `payments`, y determina el producto y el tipo de **Link** que se creará.                                                                                                                                                                                                                                                                  |
| `country`       | `string` | El parámetro `country` debe ser el código `ISO 3166-1 alfa-2` del país al que estás intentando conectarte. Puede ser `cl` o `mx`. Por defecto es `cl`. **Este parámetro no es requerido para el producto Payment Initiation**.                                                                                                                                                                                        |
| `webhook_url`   | `string` | \* \*Solo se usa para los productos `movements` e `invoices`\*\*, si estás integrando `payments` o `subscriptions` no lo necesitas.<br /><br />El parámetro `webhook_url` corresponde a la URL que recibirá una solicitud con el nuevo **Link** después de su creación exitosa, incluyendo su **link\_token**.                                                                                                        |
| `session_token` | `string` | **Solo se usa para el producto Payment Initiation**<br />El parámetro `sessionToken` corresponde al token creado por el backend al crear un [Checkout Session](https://dash.readme.com/go/fintoc?redirect=%2Fv2023-11-15%2Freference%2Fcreate-checkout-session) y se usa para desplegar y configurar el Widget.                                                                                                       |
| `widget_token`  | `string` | El parámetro `widget_token` corresponde al token creado por el backend que inicializa y configura el widget para el producto Subscriptions.<br /><br />Por ahora, solo el producto `subscriptions` usa un parámetro `widget_token`.                                                                                                                                                                                   |

También puedes incluir parámetros anidados en tu query usando el siguiente formato de query string:

```text theme={null}
queryString = "
  public_key=pk_live_XXX
  &holder_type=individual
  &product=movements
  &country=cl
  &link_token=pi_XXX
"
```

## Ejemplo de uso

Aquí hay algunos *snippets* para que empieces lo más rápido humanamente posible:

```kotlin theme={null}
override fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)
  setContentView(R.layout.activity_main)
  supportActionBar?.hide()
    
  val widgetInitizalizationUrl = generateWidgetInitializationUrl()
  
  // Modify Webview settings - all of these settings may not be applicable
  // or necessary for your integration.
  val fintocWebview = findViewById<WebView>(R.id.webview)
  val webSettings = fintocWebview.settings
  webSettings.javaScriptEnabled = true
  webSettings.javaScriptCanOpenWindowsAutomatically = true
  webSettings.domStorageEnabled = true
  webSettings.cacheMode = WebSettings.LOAD_NO_CACHE
  webSettings.useWideViewPort = true
  WebView.setWebContentsDebuggingEnabled(true)

  fintocWebview.loadUrl(widgetInitizalizationUrl.toString())
}

private fun generateWidgetInitializationUrl() : Uri {
  val builder = Uri.parse("https://webview.fintoc.com/widget.html")
    .buildUpon()
    .appendQueryParameter("product", "payments")
    .appendQueryParameter("public_key", "pk_live_INSERT_YOUR_API_KEY")
    .appendQueryParameter("session_token", "pi_INSERT_YOUR_sec_SESSION_TOKEN")
    return builder.build()
}
```

```swift theme={null}
import UIKit
import WebKit

class ViewController: UIViewController, WKNavigationDelegate, UIScrollViewDelegate, WKUIDelegate {

    private var webView: WKWebView!

    override func loadView() {
        let webConfiguration = WKWebViewConfiguration()
        webView = WKWebView(frame: .zero, configuration: webConfiguration)
        webView.uiDelegate = self
        view = webView
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        webView.navigationDelegate = self
        webView.allowsBackForwardNavigationGestures = false
        webView.scrollView.bounces = false
        webView.isMultipleTouchEnabled = false
       	webView.configuration.preferences.javaScriptCanOpenWindowsAutomatically = true

        // zoom
        webView.scrollView.delegate = self
        webView.scrollView.minimumZoomScale = 1.0
        webView.scrollView.maximumZoomScale = 1.0

        let url = generateInitializationURL()
        webView.load(URLRequest(url: url))
    }

    override var prefersStatusBarHidden : Bool {
        return true
    }

    @objc(scrollViewWillBeginZooming:withView:) func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) {
        scrollView.pinchGestureRecognizer?.isEnabled = false
    }

  	func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
        if navigationAction.targetFrame == nil {
            webView.load(navigationAction.request)
        }
        if let url = navigationAction.request.url {
            UIApplication.shared.open(url)
        }
        return nil
    }

    func generateInitializationURL() -> URL {
        let params = [
            "holder_type": "individual",
            "product": "payments",
            "public_key": "pk_live_INSERT_YOUR_API_KEY",
            "widget_token": "pi_INSERT_YOUR_sec_WIDGET_TOKEN",
        ]
        var components = URLComponents()
        components.scheme = "https"
        components.host = "webview.fintoc.com"
        components.path = "/widget.html"
        let queryItems = params.map { URLQueryItem(name: $0, value: $1) }
        components.queryItems = queryItems
        return components.url!
    }
  
    func webView(
      _ webView: WKWebView,
      decidePolicyFor navigationAction: WKNavigationAction,
      decisionHandler: @escaping ((WKNavigationActionPolicy) -> Void)
    ) {
      guard let url = navigationAction.request.url else {
        decisionHandler(.allow)
        return
      }
      let linkScheme = "fintocwidget";
      let actionScheme = url.scheme;
      let actionType = url.host ?? "";
      if actionScheme == linkScheme {
        switch actionType {
          case "succeeded":
          	print("Succeeded!")
          	break
          case "exit":
          	print("Exited")
          	break
          default:
          	print("Another widget action detected: \(actionType)")
          	break
        }
        decisionHandler(.cancel)
        return
      } else {
        decisionHandler(.allow)
      }
}
```

Fíjate que el ejemplo en Swift tiene un método `webView`. Este método define qué pasa cuando un usuario hace clic en un enlace dentro del WebView. En el ejemplo, el enlace se abre en Safari, pero puedes personalizar este comportamiento a voluntad (los enlaces podrían abrirse dentro de la misma aplicación, por ejemplo). Esto es importante porque, al usar el producto [Payment Initiation](/es/v2023-11-15/docs/payments/overview-payment-initiation), después de terminar el flujo de pago el usuario puede hacer clic en un enlace para descargar el comprobante de la transacción. **Deberías permitir que los enlaces se abran**.

## Redirecciones del WebView

Una vez que el WebView esté integrado, puedes interactuar con sus eventos usando redirecciones.

| Método      | URL de redirección                                      | Descripción                                                                                                                                                                    |
| :---------- | :------------------------------------------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `onSuccess` | fintocwidget://succeeded                                | Este evento ocurrirá después de que el flujo termine exitosamente.                                                                                                             |
| `onExit`    | fintocwidget://exit                                     | Este evento ocurrirá después de que un usuario cierre el Widget prematuramente.                                                                                                |
| `onEvent`   | fintocwidget://event/\{event\_name}?queryparam=\{value} | Este evento ocurrirá en cada evento disponible en el widget. Puedes encontrar más información sobre estos eventos [aquí](/es/v2023-11-15/docs/resources/widget/widget-events). |

<Warning>
  **onEvent (WebView)**

  El evento `onEvent` para WebView está deshabilitado por defecto y se puede habilitar pasando el *queryparam* `_on_event={any_value}` como parámetro de `https://webview.fintoc.com/widget.html` (por ejemplo: `https://webview.fintoc.com/widget.html?[...]&_on_event=true`). Una vez habilitado, será posible recibir eventos `onEvent`. A partir del **1 de mayo de 2023**, esta funcionalidad estará habilitada por defecto, por lo que es necesario manejar la redirección `onEvent` antes de esta fecha para evitar romper la integración con el Widget.
</Warning>

Para usar estos métodos en Android e iOS, puedes usar los siguientes *snippets*:

```kotlin theme={null}
webview.webViewClient = object : WebViewClient() {
  override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
    val parsedUri = Uri.parse(url)
    if (parsedUri.scheme.equals("fintocwidget")) {
      val action: String? = parsedUri.host
      val linkData: HashMap<String, String?>? = parseLinkUriData(parsedUri)
      if (action.equals("succeeded")) {
        // onSuccess
      }
      if (action.equals("exit")) {
        // onExit
      }
    }
    return true
  }
}
```

```java theme={null}
webview.setWebViewClient(new WebViewClient() {
  public boolean shouldOverrideUrlLoading(WebView view, String url) {
    Uri parsedUri = Uri.parse(url);
    if (parsedUri.getScheme().equals("fintocwidget")) {
      String action = parsedUri.getHost();
      HashMap<String, String> linkData = parseLinkUriData(parsedUri);
      if (action.equals("succeeded")) {
        // onSuccess
      }
      if (action.equals("exit")) {
        // onExit
      }
    }
  }
}
```

```swift theme={null}
func webView(
          _ webView: WKWebView,
          decidePolicyFor navigationAction: WKNavigationAction,
          decisionHandler: @escaping ((WKNavigationActionPolicy) -> Void)
        ) {
          guard let url = navigationAction.request.url else {
            decisionHandler(.allow)
            return
          }
          let linkScheme = "fintocwidget";
          let actionScheme = url.scheme;
          let actionType = url.host ?? "";
          if actionScheme == linkScheme {
            switch actionType {
            case "succeeded":
              // onSuccess
              break
            case "exit":
              // onExit
              break
            default:
              print("Widget action detected: \(actionType)")
              break
            }
            decisionHandler(.cancel)
            return
          } else {
            decisionHandler(.allow)
          }
    }
```

<Warning>
  **iOS - agregar fintocwidget como URL Scheme**

  Antes de integrar el widget de Fintoc con tu app de iOS, es importante agregar **fintocwidget** como un URL scheme permitido dentro del archivo Info.plist de la app. Esto es requerido por razones de seguridad.
</Warning>

```xml theme={null}
<key>CFBundleURLTypes</key>
	<array>
		<dict>
			<key>CFBundleURLSchemes</key>
			<array>
				<string>fintocwidget</string>
			</array>
			<key>CFBundleURLName</key>
			<string>your.bundle.id</string>
		</dict>
	</array>
```
