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

# 4. Results and cleanup

> Handle callbacks, confirm payments on your backend and clean up the form.

<div className="ao-guide-rail not-prose"><a href="/en/virtual-payments/checkout-web/introduction">← Checkout Web overview</a><span>STEP 04 / 05</span></div>

When you call `paymentForm.init(...)`, Flex It allows you to capture three callback functions. The most important result for front `responseCallback(response)`.

<Info>
  Here. `responseCallback(response)` as the main entrance of the result at front. The JSON That you get there reuses the same structure of **API of Authorisation - ecommerce** for the method of payment chosen within Flex.
</Info>

## Callbacks available

<CardGroup cols={3}>
  <Card title="responseCallback" icon="circle-check">
    It runs when the process gets to a business result and gives you the JSON response.
  </Card>

  <Card title="trackingCallback" icon="chart-line">
    It runs for every flow event, as a method change, clicks or user advance within the form.
  </Card>

  <Card title="Failed" icon="circle-xmark">
    It runs after a technical error occurs during the load or performance of the component.
  </Card>
</CardGroup>

## Example of implementation

```javascript theme={"system"} theme={"system"}
function responseCallback(response) {
    console.log("-------Respuesta-------");
    console.log({response});
}

function trackingCallback(trackdata) {
    console.log("-------Tracking de Eventos-------");
    console.log({trackdata});
}

function onErrorCallback(error) {
    console.log("-------Error en el proceso-------");
    console.log({error});
}

paymentForm.init(
    document.querySelector("#demo"),
    responseCallback,
    trackingCallback,
    onErrorCallback
);
```

## How to interpret responseCallback

<Note>
  The field `response.payment_method` indicates what reference to PayIn you have to use to interpret the JSON response returned by Flex.
</Note>

<Warning>
  Do not use `response.meta.status.code` as an approved or refused payer. That code indicates only the result of the service processing or if the response was generated correctly. To validate the payment result, check `response.transaction.state` and confirms from backend with [Consultation](/en/api-reference/payin/get-ecommerce-transaction) or [Notifications](https://docs.pay-me.com/payin/notificaciones)with the method of payment.
</Warning>

<Tabs>
  <Tab title="CARD">
    The object `response` following the contract of [API from Authorisation with Card](https://docs.pay-me.com/payin/autorizacion-tarjeta).

    If your flow uses Redirect or 3DS authentication outside the same screen, complete this reading with [Considerations for Redirect methods](https://docs.pay-me.com/payin/autorizacion-metodos-con-redirect).
  </Tab>

  <Tab title="YAPE">
    The object `response` following the contract of [API from Authorisation with Yape](https://docs.pay-me.com/payin/autorizacion-yape).

    Even if the result goes by `responseCallback`, also valid operative consistency from backend before confirming order.
  </Tab>

  <Tab title="BANK_TRANSFER">
    The object `response` following the contract of [API with Bank Transfer](https://docs.pay-me.com/payin/autorizacion-transferencia-bancaria).

    That method may require later confirmation. Do not take the front as the only source of truth: get up at [Consultation](https://docs.pay-me.com/payin/consulta-transferencia-bancaria) or [Notifications](https://docs.pay-me.com/payin/notificaciones).
  </Tab>

  <Tab title="QR">
    The object `response` following the contract of [API from Authorisation with QR](https://docs.pay-me.com/payin/autorizacion-qr).

    To generate QR or showing an initial response does not amount to a confirmed final payment. Use [Consultation](https://docs.pay-me.com/payin/consulta-qr) or [Notifications](https://docs.pay-me.com/payin/notificaciones) To close up his business logic.
  </Tab>

  <Tab title="CUOTEALO">
    The object `response` following the contract of [API from Authorisation with Cuotéalo](https://docs.pay-me.com/payin/autorizacion-cuotealo).

    The final status with a redirection or monitoring flow confirms [Consultation](https://docs.pay-me.com/payin/consulta-cuotealo) or [Notifications](https://docs.pay-me.com/payin/notificaciones).
  </Tab>

  <Tab title="PAGOEFECTIVO">
    The object `response` following the contract of [API from Authorisation with PagoEfectivo](https://docs.pay-me.com/payin/autorizacion-pagoefectivo).

    The generation of CIP or from the payment link doesn't mean that the money's been received. confirms the result with [Consultation](https://docs.pay-me.com/payin/consulta-pagoefectivo) or [Notifications](https://docs.pay-me.com/payin/notificaciones).
  </Tab>
</Tabs>

<Warning>
  `trackingCallback` and `onErrorCallback` for technical faults. No one replaces the business logic you have to build up about `responseCallback` and backend confirmation.
</Warning>

## Life cycle of the instance

<Note>
  The following examples use `unmountFlex()` from the [responsive example](/en/virtual-payments/checkout-web/customize-checkout#responsive-conduct). Adapt cleanup to your presentation: embedded, popup or expanded.
</Note>

`paymentForm.terminate?.()` complete the internal processes, list and resources that maintain the Flex. That operation is different from eliminating the form from DOM (`flexContainer.innerHTML = ""`) and applying to any type of presentation.

<Info>
  The operator `?.` run `terminate()` only when the method exists. That prevents an error if the loaded version of Flex Do not implement that method.
</Info>

### When to dismount according to presentation

| Presentation  | When to Unmount                                                               | Following visual action                                      |
| :------------ | :---------------------------------------------------------------------------- | :----------------------------------------------------------- |
| Drink         | When you hide the checkout, you change Section or navigate to another screen. | Withdraw or replace the constore where it was Flex.          |
| Popup (modal) | When the buyer closes his pup or his flow ends.                               | Hide the overlay and return the focus to the main interface. |
| Expand        | When you get a check out or leave an expanded vision.                         | Take the panel or restore the earlier Layout.                |

In all 3 cases, first process any outstanding result and then run `unmountFlex()` before updating the visual presentation.

<Warning>
  Do not modify the internal styles of Flex. Execut `unmountFlex()` When you withdraw the form, regardless of whether it's embedded, into a popup or an expanded view.
</Warning>

### own result screen

When you set up `settings.display_result_screen: false`, Flex doesn't have his final screen. Your application should get the `response`, evaluate the status of the transaction and display an own result screen.

<Steps>
  <Step title="Mount form">
    `paymentForm.init(...)` challenges Flex inside the container.
  </Step>

  <Step title="Receives result">
    Flex run `responseCallback(response)`. Read the result from `response.transaction.state` and conduct related business validations.
  </Step>

  <Step title="Show your screen">
    Save the `response` at the status of your application and navigate or render the result screen from the merchant.
  </Step>

  <Step title="Unmount Flex">
    When the result has been processed, run `terminate()`, cleanes the container and updates the presentation drunk, popup or expanded.
  </Step>
</Steps>

```javascript theme={"system"} theme={"system"}
const paymentForm = new FlexPaymentForms({
  nonce,
  payload,
  settings: {
    display_result_screen: false
  }
});

const flexContainer = document.querySelector("#flex-container");

paymentForm.init(
  flexContainer,
  (response) => {
    const transactionState = response.transaction?.state;

    // Procesa y conserva la respuesta antes de desmontar Flex.
    showMerchantResultScreen({ transactionState, response });
    unmountFlex();
  },
  (tracking) => {
    console.log("Evento de seguimiento", tracking);
  },
  (error) => {
    console.error("Error de Flex", error);
  }
);
```

<Warning>
  Don't run `terminate()` before receiving and processing `responseCallback(response)`. If you finish the instance earlier, you can stop the flow and lose the result that Flex He's been put up.
</Warning>

### Reusable cleaning

It encapsulates initiation and dismantling into an independent framework controller. You can use them from pure JavaScript or connect them to React's life cycle, Vue, Angular or other technologies.

```javascript theme={"system"} theme={"system"}
function createFlexController({
  container,
  configuration,
  onResult,
  onTracking,
  onError
}) {
  let instance = null;

  function mount() {
    // Evita conservar una instancia anterior al volver a abrir Flex.
    destroy();

    instance = new FlexPaymentForms(configuration);
    instance.init(container, onResult, onTracking, onError);
  }

  function destroy() {
    instance?.terminate?.();
    instance = null;
    container.replaceChildren();
  }

  return { mount, destroy };
}

const flexController = createFlexController({
  container: document.querySelector("#flex-container"),
  configuration: {
    nonce,
    payload,
    settings: {
      display_result_screen: false
    }
  },
  onResult: responseCallback,
  onTracking: trackingCallback,
  onError: onErrorCallback
});

// Abre o vuelve a crear el formulario.
flexController.mount();

// Finaliza la instancia al cerrar, navegar o retirar la presentación.
// flexController.destroy();
```

<CardGroup cols={3}>
  <Card title="JavaScript" icon="code">
    Execut `destroy()` before withdrawing the container from the page.
  </Card>

  <Card title="Implementation SPA" icon="arrows-rotate">
    Connect `destroy()` to change of path or to dismount vision.
  </Card>

  <Card title="Dynamic presentation" icon="window-restore">
    Do so by hiding the embossed block, closing the Popup or getting an expanded view.
  </Card>
</CardGroup>

`container.replaceChildren()` an empty constore equivalent to `container.innerHTML = ""`without dependent on a specific framework.

<Note>
  `terminate()` does not return the payment response. The result always comes with the first call of `paymentForm.init(...)`. Check. [Capture callback functions](/en/virtual-payments/checkout-web/results-and-cleanup) to interpret and confirm the operation.
</Note>

### Management of closure with show\_close\_button

Figure `settings.show_close_button: true` to display the native clasp of Flex. That option works with embumbing, pounding and expanding presentations.

```javascript theme={"system"} theme={"system"}
const paymentForm = new FlexPaymentForms({
  nonce,
  payload,
  settings: {
    show_close_button: true
  }
});
```

When the buyer presses the button, Flex send message `cerro el carrito` with `onErrorCallback`. Although using the error call, this message represents a voluntary action by the buyer and not a technical failure.

<CardGroup cols={3}>
  <Card title="Show the button" icon="circle-xmark">
    Active `show_close_button` inside `settings`.
  </Card>

  <Card title="Play the event" icon="code-branch">
    Identifies the exact message `cerro el carrito` in `onErrorCallback`.
  </Card>

  <Card title="Close presentation" icon="power-off">
    Execut `onClose()` for dismantling Flex and update the interface.
  </Card>
</CardGroup>

It implements an exclusive branch for voluntary closure and preserves other messages as technical errors:

```javascript theme={"system"} theme={"system"}
function getFlexErrorMessage(error) {
  if (typeof error === "string") return error;
  return error?.message ?? "";
}

function onErrorCallback(error) {
  const errorMessage = getFlexErrorMessage(error).trim();

  if (errorMessage === "cerro el carrito") {
    onClose();
    return;
  }

  // Los demás mensajes se procesan como errores técnicos.
  handleFlexError(error);
}

function onClose() {
  unmountFlex();

  // Oculta el popup, retira el bloque embebido o contrae la vista expandida.
  hideFlexPresentation();
}
```

The closing flow is `show_close_button` → `onErrorCallback` → `onClose()` → `unmountFlex()`. `hideFlexPresentation()` represents the visual logic of your application: remove the embedded block, hide the popup or get an expanded view.

<Warning>
  Execut `onClose()` only after complete message `cerro el carrito`. Any other value received at `onErrorCallback` have to continue to manage technical errors.
</Warning>

<Card title="5. Testing and production" icon="arrow-right" href="/en/virtual-payments/checkout-web/testing-and-production">Review security, functional tests and production readiness.</Card>
