React, loading a script inside a form (mercadopago)

Viewed 484

I am trying to implement some payment system (MercadoPago).

According to the doc, it's just pasting this:

<form method="POST">
  <script
    src="https://www.mercadopago.com.pe/integrations/v1/web-payment-checkout.js"
    data-preference-id="589788715-2e52aeec-8275-487c-88ee-1a08cff37c08"
  ></script>
</form>

Pasting it in a pure html file works fine: a button appears and clicking it opens a modal to pay with a credit card as expected. However this doesn't work in React since it's dynamically loading a script. Hence, I tried using an effect hook to insert the <script> on load as such:

const App = () => {
  const setMercadoPagoPreferences = async () => {
    const script = document.createElement('script');
    script.src =
      'https://www.mercadopago.com.ar/integrations/v1/web-payment-checkout.js';
    script.async = true; // commenting or uncommenting seems to have no effect
    script.setAttribute(
      'data-preference-id',
      '589788715-2e52aeec-8275-487c-88ee-1a08cff37c08'
    );
    document.getElementById('mercadoForm').appendChild(script);
  };

  useEffect(() => {
    setMercadoPagoPreferences();
  }, []);

  return <form action='/procesar-pago' method='POST' id='mercadoForm' />;
};

This loads correctly the script, it seems, as a button to pay is appended to the page. Clicking it however opens a modal that says "oh no, something bad happened". This doesn't happen on my .html example above; so it must be because of how React is loading the script or something like that. It doesn't work on either the dev or the production build.

Edit: As suggested, I tried using refs instead of directly appending childs but this did not seem to have any impact, it still won't work.

2 Answers

I dont know this framework but maybe thats the way: It looks like this guy has similar problem right here.

I think there is problem because script does not load on time. So maybe lets try this:

script.onload = () => {
  document.getElementById('mercadoForm').appendChild(script);
};

In addtion there is build in mechanism in react ref like HERE instead of document.getElementById

Your technique would've work if it weren't for mercadolibre. Apparently, the use of the page you are trying to load is not allowed by mercadolibre. It's like you're trying to load mercadolibre inside an Iframe which they probably blocked using CSP header. Specifically they are setting the Content-Security-Policy tag to frame-ancestors 'self'. It's a security restriction standard that does not allow the use of pages from that domain within elements Iframe.

Related