javascriptapiauthenticationmercadopagomercadopagosdk

Error: MercadoPago.js - Could not find HTML element for provided id: MPHiddenInputPaymentMethod


I have an Nuxt desktop app here, am i am facing this problem with MERCADO PAGO API.

This is part of the Mercado documentation : https://www.mercadopago.com.br/developers/pt/guides/online-payments/checkout-api/v2/testing

The problem is: enter image description here

I make use of the index.vue that makes use of the default form from the documentation itself:

    <template>
  <div >
   <form id="form-checkout" >
   <input type="text" name="cardNumber" id="form-checkout__cardNumber" />
   <input type="text" name="cardExpirationMonth" id="form-checkout__cardExpirationMonth" />
   <input type="text" name="cardExpirationYear" id="form-checkout__cardExpirationYear" />
   <input type="text" name="cardholderName" id="form-checkout__cardholderName"/>
   <input type="email" name="cardholderEmail" id="form-checkout__cardholderEmail"/>
   <input type="text" name="securityCode" id="form-checkout__securityCode" />
   <select name="issuer" id="form-checkout__issuer"></select>
   <select name="identificationType" id="form-checkout__identificationType"></select>
   <input type="text" name="identificationNumber" id="form-checkout__identificationNumber"/>
   <select name="installments" id="form-checkout__installments"></select>
   <button type="submit" id="form-checkout__submit">Pagar</button>
   <progress value="0" class="progress-bar">Carregando...</progress>
</form>
  </div>
</template>

nuxt.config:

export default{
head:{
...
script: [
      { src: 'https://sdk.mercadopago.com/js/v2' },
      {src: "/js/index.js", },
}
}

and the "/js/index.js file in static folder:

//i know the YOU_PUBLIC_KEY must be from the Mercado Pago account, i have one already
  const mp =  new MercadoPago('YOUR_PUBLIC_KEY', {
    locale: 'pt-BR',
  })
  const cardForm = mp.cardForm({
    amount: '100.5',
    autoMount: true,
    processingMode: 'aggregator',
    form: {
      id: 'form-checkout',
      cardholderName: {
        id: 'form-checkout__cardholderName',
        placeholder: 'Cardholder name',
      },
      cardholderEmail: {
        id: 'form-checkout__cardholderEmail',
        placeholder: 'Email',
      },
      cardNumber: {
        id: 'form-checkout__cardNumber',
        placeholder: 'Card number',
      },
      cardExpirationMonth: {
        id: 'form-checkout__cardExpirationMonth',
        placeholder: 'MM'
      },
      cardExpirationYear: {
        id: 'form-checkout__cardExpirationYear',
        placeholder: 'YYYY'
      },
      securityCode: {
        id: 'form-checkout__securityCode',
        placeholder: 'CVV',
      },
      installments: {
        id: 'form-checkout__installments',
        placeholder: 'Total installments'
      },
      identificationType: {
        id: 'form-checkout__identificationType',
        placeholder: 'Document type'
      },
      identificationNumber: {
        id: 'form-checkout__identificationNumber',
        placeholder: 'Document number'
      },
      issuer: {
        id: 'form-checkout__issuer',
        placeholder: 'Issuer'
      }
    },
    callbacks: {
      onFormMounted: error => {
        if (error) return console.warn('Form Mounted handling error: ', error)
        console.log('Form mounted')
      },
      onFormUnmounted: error => {
        if (error) return console.warn('Form Unmounted handling error: ', error)
        console.log('Form unmounted')
      },
      onIdentificationTypesReceived: (error, identificationTypes) => {
        if (error) return console.warn('identificationTypes handling error: ', error)
        console.log('Identification types available: ', identificationTypes)
      },
      onPaymentMethodsReceived: (error, paymentMethods) => {
        if (error) return console.warn('paymentMethods handling error: ', error)
        console.log('Payment Methods available: ', paymentMethods)
      },
      onIssuersReceived: (error, issuers) => {
        if (error) return console.warn('issuers handling error: ', error)
        console.log('Issuers available: ', issuers)
      },
      onInstallmentsReceived: (error, installments) => {
        if (error) return console.warn('installments handling error: ', error)
        console.log('Installments available: ', installments)
      },
      onCardTokenReceived: (error, token) => {
        if (error) return console.warn('Token handling error: ', error)
        console.log('Token available: ', token)
      },
      onSubmit: (event) => {
        event.preventDefault();
        const cardData = cardForm.getCardFormData();
        console.log('CardForm data available: ', cardData)
      },
      onFetching: (resource) => {
        console.log('Fetching resource: ', resource)

        // Animate progress bar
        const progressBar = document.querySelector('.progress-bar')
        progressBar.removeAttribute('value')

        return () => {
          progressBar.setAttribute('value', '0')
        }
      },
    }
  })

Anyone can help me with this? And is facing more problems with the MERCADO PAGO's API?

Thanks for the atention!


Solution

  • Use iframe to render custom vanilla HTML/CSS/JS.

    I'm using vue/quasar2 and my workaround was using an Iframe to render a custom page which can use this lib, you can see the directory structure here.

    I created a page to and use an iframe tag to render the custom page:

    <template>
      <q-page class="flex flex-center">
        <iframe width="100%" height="545vh" style="border: none;" :src='`static_site/index.html?obj=${JSON.stringify(getQueryParameters())}`'/>
      </q-page>
    </template>
    
    <script>
    import { defineComponent } from 'vue';
    
    export default defineComponent({
      name: 'PageIndex',
    
      setup () {
    
        function getQueryParameters () {
          return {
            name: "name",
            email: "name@gmail.com",
            valor: "20"
          }
        }
    
        return {
          getQueryParameters,
        }
      }
    })
    </script>
    

    I'm using the query parameters ( obj ) in the iframe src to pass down information from vue to the lib. In the callbacks section of the cardForm function, I used the URLSearchParams object to catch the information I sended, you can see it here.

    OBS: I just found this workaround yesterday and haven't tested in production yet, but in dev it's working fine, will test soon in production and update this answer, hope it's useful to you.