0

I'm creating a integration with a payment service. The payment service provides me a form with a script tag inside.

My question is a continuation from Insert a script tag inside template Vue

The form with checkout of payment service:

<form action="http://localhost:8081/api/v1/payment/" method="POST">
      <script
        src="https://www.mercadopago.com.br/integrations/v1/web-tokenize-checkout.js"
        data-public-key="KEY"
        data-transaction-amount="14.90">
      </script>
</form>

I can make the next on "mounted()" of vuejs:

<form ref="myform">
  ...
</form>

mounted() {
  let foo = document.createElement('script');    
  foo.setAttribute("src","https://www.mercadopago.com.br/integrations/v1/web-tokenize-checkout.js");
  foo.setAttribute("data-transaction-amount", this.newAmount)
  this.$refs.myform.appendChild(foo);
}

But, my problem is that after the view has been mounted. the user can change "data-transaction-amount".

To solve it , I tried:

data:()=>({
  newAmount:0
})

watch: {
    newAmount() {
      this.modifyScript();
    },
  },
  methods: {
    modifyScript() {
      let scripts = document.getElementsByTagName("script");
      for (let i = 0; i < scripts.length; i++) {
        let script = scripts[i];
        if (script.getAttribute("src") == 'https://www.mercadopago.com.br/integrations/v1/web-tokenize-checkout.js') {
          // we've got a match
          script.setAttribute("data-transaction-amount", this.newAmount);
        }
      }
    },

The "data-transaction-amount" is changing to new value, but the window checkout of payment service shows the original value used in "mounted()".

4
  • did you try scripts[i].setAttribute("data-transaction-amount", this.newAmount);? Commented Aug 13, 2020 at 22:54
  • This sounds like a problem you need to raise with the provider of that script. Ask them how to update the transaction amount dynamically Commented Aug 13, 2020 at 23:15
  • Yes, I did. As I said, this is not the problem. In chrome console debugger, I can see It is working. The problem is that the window payment service is showing the old value used during the "mounted" cycle, instead of new value. Commented Aug 13, 2020 at 23:16
  • @Phil I think this is not an option. The provider is a big player "mercadopago". I guess they are not worry about it. Commented Aug 13, 2020 at 23:19

1 Answer 1

2

One solution should be let the browser force to reload the javascript file after the amount is changed.

Below is one steps:

  1. adds one version# into the end of the URL
  2. when amount is changed, removes the script element (src=...?old_amount) already added before
  3. adds new script element (src=...?new_amount)

Below is one fiddle (open the browser console, then you will see the script web-tokenize-checkout.js is redownloaded when the amount is changed).

Vue.component('v-loadjs',{
    template:`
        <div>
            <p><button class="btn btn-info" v-on:click="changeAmount()">Change Amount: {{amount}}</button></p>
            <p ref="test"></p>
        </div>
    `,
    data () {
      return {
        amount: 0,
        url: 'https://www.mercadopago.com.br/integrations/v1/web-tokenize-checkout.js'
      }
    },
    mounted: function () {
      this.loadJS(this.amount, this.amount)
    },
    watch: {
      amount: function(newAmount, oldAmount) {
        this.loadJS(newAmount, oldAmount)
      }
    },
    methods: {
      changeAmount: function () {
        this.amount += 1
      },
      loadJS: function (newAmount, oldAmount) {
        [...document.querySelectorAll('button.mercadopago-button')].forEach(item => item.remove())
        let scripts = document.getElementsByTagName("script");
        for (let i = 0; i < scripts.length; i++) {
          if (scripts[i].getAttribute("src") == this.url + '?version=' + oldAmount) {
            scripts[i].remove()
          }
        }
        let foo = document.createElement('script');    
        foo.setAttribute("src", this.url + '?version=' + newAmount);
        foo.setAttribute("data-transaction-amount", newAmount)
        this.$refs.test.appendChild(foo);
      }
    }
})

new Vue ({
  el:'#app'
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
    <div class="container">
        <div class="col-lg-offset-4 col-lg-4">
            <v-loadjs></v-loadjs>
        </div>
    </div>
</div>

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.