DEV Community

Cover image for Use Paypal Smart Button as Vue Component (Part 2 of 3)
Galih Muhammad
Galih Muhammad

Posted on

Use Paypal Smart Button as Vue Component (Part 2 of 3)

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.

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

  </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>
Enter fullscreen mode Exit fullscreen mode

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

    <!-- TODO: Put the paypal button here -->
    <div class="buynow">
      <paypal-button
        refer="paypal-container-<%= product.id.to_s %>"
      />
    </div>
Enter fullscreen mode Exit fullscreen mode

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

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
    }
  })
})

Enter fullscreen mode Exit fullscreen mode

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

%= javascript_pack_tag     'store' %>
Enter fullscreen mode Exit fullscreen mode
  • Add Paypal JS SDK using yarn
yarn add @paypal/sdk-client
Enter fullscreen mode Exit fullscreen mode

then add to the store.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', () => {
Enter fullscreen mode Exit fullscreen mode
  • Create the vue component: paypal button

app/javascript/components/paypal_button.vue

<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>
Enter fullscreen mode Exit fullscreen mode

The last thing for this step is to hook this newly-created component onto the store.js pack

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
    }
  })
})
Enter fullscreen mode Exit fullscreen mode

Notice that we have just added this line:

    components: {
      PaypalButton
    }
Enter fullscreen mode Exit fullscreen mode

and this line:

el: '#store-list',
Enter fullscreen mode Exit fullscreen mode

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

<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>
Enter fullscreen mode Exit fullscreen mode

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


// 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>
Enter fullscreen mode Exit fullscreen mode

Up to this point, your component should be ok enough that it will re-appear and working once more.

Alt Text

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

Top comments (0)