Use Paypal Smart Button as Vue Component (Part 2 of 3)
Tags: rails, paypal, payment, javascript
Published: 2020-11-30 14:22:08

---
title: Use Paypal Smart Button as Vue Component (Part 2 of 3)
series: Easy Paypal Checkout in Rails
published: true
description: How to convert Paypal Smart button into a Vue component to quickly create checkout system in Rails in less code than ever before
tags: rails,paypal,payment,javascript
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/r5tm9b3th49xew9b7p98.png
---

Right, from the previous post we have managed to add the Paypal Smart payment buttons easily. But the buttons, though are functioning, not really do much in terms of providing a way for our customers to pay for our goods or services.

In this post, we will start the journey of making the buttons dynamic, ie. able to charge our customers correctly based on the price of the goods, and once they completed the payment, allow them to access the download link.

If you want to code along with this post, you can do so by checking out from [this commit on indiesell repo](https://github.com/galliani/Indiesell/tree/c389934f61b31294cda7bf0b3652de9275b822c1).


##  Convert the button to vue component

Remove the second script that we added on the layout template so that it will only look like this:

app/views/layouts/store/application.html.erb
```html
  </footer>

    <script
    id="paypal-sdk-js-src"
    src="https://www.paypal.com/sdk/js?client-id=<%= ENV['paypal_client_id'] %>"
    data-sdk-integration-source="button-factory"
  >
  </script>
</body>
```

Only keep the script source from Paypal, then we add the button container, by replacing the previous button html on the product item partial html

app/views/store/products/_product.html.erb
```html
    <!-- TODO: Put the paypal button here -->
    <div class="buynow">
      <paypal-button
        refer="paypal-container-<%= product.id.to_s %>"
      />
    </div>
```
Now if you refresh, the button will disappear, our mission for the next 5 mins is to make that re-appear

- Intro for the vue pack: store.js

This is the current state of the Vue pack that will be responsible to hold all the javascripts needed to easily get our Paypal button to be dynamic.

app/javascript/packs/store.js
```js
import Vue from 'vue/dist/vue.esm'

document.addEventListener('DOMContentLoaded', () => {
  var storeList = new Vue({
    el: '', // Add the css identifier for the div that will load the paypal button
    components: {
      // Add paypal button here
    }
  })
})

```

This Vue pack is already hooked to our rails HTML template on the layout template for the storefront.

app/views/layouts/store/application.html.erb:13
```html
%= javascript_pack_tag     'store' %>
```

- Add Paypal JS SDK using yarn
```sh
yarn add @paypal/sdk-client
```

then add to the store.js
```js
import Vue from 'vue/dist/vue.esm'
// add this single line below here to use the Paypal JS SDK we've just installed
import { unpackSDKMeta } from '@paypal/sdk-client';

document.addEventListener('DOMContentLoaded', () => {
```

- Create the vue component: paypal button

app/javascript/components/paypal_button.vue
```js
<template>
  <div :id="refer"></div>
</template>

<script>
export default {
  props: {
    // This is for giving dynamic container css 'ID' to be called by the Paypal button renderer
    refer: {
      type: String,
      required: true
    }    
  },
  data() {
  },
  mounted: function() {
  },
  computed: {
  },
  methods: {
  }
}
</script>
```

The last thing for this step is to hook this newly-created component onto the store.js pack
```js
import Vue from 'vue/dist/vue.esm'
import { unpackSDKMeta } from '@paypal/sdk-client';
// Add this single line below
import PaypalButton from '../components/paypal_button.vue';

document.addEventListener('DOMContentLoaded', () => {
  var storeList = new Vue({
    el: '#store-list', // Add the css identifier for the div that will load the paypal button
    components: {
      // Add paypal button here
      PaypalButton
    }
  })
})
```
Notice that we have just added this line:
```
    components: {
      PaypalButton
    }
```
and this line:
```
el: '#store-list',
```
but for this line to be working, we need to remember to add this element identifier onto the rails template also

app/views/store/products/index.html.erb
```html
<div
  class="section section-demo"
  id="store-list" <!-- This is what we add -->
>
  <div class="container">
    <%= render partial: "product", collection: @products, as: :product %>
  </div>
</div>
```

Two lines, that's it. We will not be adding anymore to this file.

So the setup is ready, all we need to do now is to get the component working.

- Setup the vue component: paypal button

app/javascript/components/paypal_button.vue
```js

// REDACTED //

<script>
export default {
  props: {
    refer: {
      type: String,
      required: true
    },
    // This is where will pass more product attributes to be used in this vue component from the rails html template
  },
  data() {
    return {
      // Defaults template for the order JSON payload that will be sent to Paypal
      order: {
        description: "",
        amount: {
          currency_code: "",
          value: 0
        }
      }
    };
  },
  mounted: function() {
    // IMPORTANT: this method causes the paypal button be loeaded and rendered
    this.setLoaded();
  },
  computed: {
    selectorContainer() {
      return '#' + this.refer;
    }
  },
  methods: {
    setLoaded: function() {
      paypal
        .Buttons({
          createOrder: (data, actions) => {
            return actions.order.create({
              purchase_units: [
                this.order
              ]
            });
          },
          onApprove: async (data, actions) => {
          },
          onError: err => {
            console.log(err);
          }
        }).render(this.selectorContainer);
    }
  }
};
</script>
```
Up to this point, your component should be ok enough that it will re-appear and working once more.


![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/56t06zqg5ug64f6prxt9.png)

On the next part, we will have the maximum fun by turning all of these hard work into fruition by tying the checkout button to our backend.

PS: reminder, if you don't want to wait, you can view the full post at [this blog post](https://rubyist.info/paypal-smart-button-checkout-in-rails)