DEV Community

Cover image for ¿Cómo Conectar Stripe a Vue?
Denisse Abreu
Denisse Abreu

Posted on • Edited on • Originally published at codingpr.com

¿Cómo Conectar Stripe a Vue?

Hola 🖐🏼, en esta guía, te enseñaré cómo conectar Stripe a Vue. Esta integración es solo para carritos de compras, no para suscripciones. Debido a la complejidad de esta integración, te dejo aquí el enlace a mi sitio web.

¿Cómo conectar Stripe a un comercio electrónico hecho con Vue js Options API? | CodingPR

Aprenda a conectar Stripe a un comercio electrónico hecho con Vue js Options API.

favicon codingpr.com

1. Configura Stripe.

  • Para comenzar con Stripe debes abrir una cuenta con Stripe, después de abrir su cuenta, vaya a la sección de desarrolladores y acceda a sus claves API. En la sección de desarrolladores, encontrarás dos claves: "publishable key" y "secret key", cópialos en tu archivo .env.

    VUE_APP_STRIPE_KEY=<YOUR-PUBLISHABLE-KEY>

Enter fullscreen mode Exit fullscreen mode

2. Integración.

  • Una vez que haya abierto su cuenta con Stripe, copia el "script tag" de stripe en el "head" de index.html.

    <head>
      <script src="https://js.stripe.com/v3/"></script>
    </head>

Enter fullscreen mode Exit fullscreen mode
  • Inmediatamente después de obtener el subtotal de la transacción, crea el "onclick event" para llamar al servidor y solicitar el payment intent. Usa la función "paymentIntent()" en diferentes partes de tu app, colocalo en el "login form" y el "guest form".

    <!-- template -->
    <v-btn
      v-if="isCart >= 1"
      block
      color="#385F73"
      class="mt-3"
      elevation="2"
      :loading=loading
      rounded
      dark
      @click="paymentIntent"
    >
      Subtotal
    </v-btn>

Enter fullscreen mode Exit fullscreen mode

    // coloque esta función en diferentes partes de su aplicación
    // methods
    paymentIntent () {
      if (this.isLoggedIn) {
        this.$store.dispatch('paymentIntent')
          .catch((_err) => {
            this.loading = false
            const show = true
            const color = 'red darken-3'
            const text = 'Server Error, try again later!'
            this.$store.commit('cartSnack', {
              show, color, text
            })
          })
      } else {
        this.$router.push('/pre-checkout')
      }
    }

Enter fullscreen mode Exit fullscreen mode
  • Para pasar las propiedades del Vue al servidor usamos como intermediario Vuex y Axios. Vuex es el manejador de "state" para aplicacciones de Vuejs y Axios el manejador de HTTP. En el siguiente código, extraiga del estado el objeto de usuario y el carrito de compras. Envíe al servidor el carrito de compras para calcular el total de la transacción según el número de id del producto. Después de enviar estos objetos, reciba la respuesta del servidor con el secreto del cliente y el cálculo de impuestos, envíelos a las mutaciones y guárdelos en el 'state'.

    // vuex actions
    async paymentIntent ({ commit, state }) {
      const res = await axios.post('users/secret/', {
        user: state.user,
        cart: state.cart
      })
      if (res.status === 201) {
        commit('CLIENT_SECRET', {
          client_secret: res.data.client_secret,
          tax: res.data.tax
        })
        router.push('/checkout')
      }
    },

Enter fullscreen mode Exit fullscreen mode

    // vuex mutations
    CLIENT_SECRET (state, payload) {
      const secret = state.secret
      secret.clientSecret = payload.client_secret
      secret.tax = payload.tax
    },

Enter fullscreen mode Exit fullscreen mode
  • Inicialice el estado con el secreto del cliente en nulo y el impuesto en 0.

    // vuex state
    state: {
      secret: {
        clientSecret: null,
        tax: 0
      },
      user: {},
      cart: []
    },

Enter fullscreen mode Exit fullscreen mode

3. Montaje del Stipe Card Element.

  • Una vez tengamos el "client secret" en el "state" podemos utilizardo para montar el Stripe Card Element. El Card Element le mostrará al cliente el formulario en el cual este insertará su número de tarjeta de crédito. Recuerda que Stripe ya tiene el total de la compra. Con el Card Element, el cliente estará autorizando y finalizando la transacción.

      <!-- template -->
      <form
        id="payment-form"
        v-if="isCart >= 1"
      >
        <br>
        <div ref="paymentElement" id="payment-element">
          <!-- El Stripe Elements insertará la forma aquí -->
        </div>
        <br>
        <div id="error-message">
          <!-- Espacio para mostrar errores -->
        </div>
      </form>
      <v-card-actions>
        <v-btn
          v-if="isCart >= 1"
          id="submit"
          :loading="loading"
          block
          color="success"
          class="mt-3"
          elevation="2"
          rounded
          dark
          @click="Submit"
        >
          Pay
        <v-icon class="ml-2">mdi-basket</v-icon>
        </v-btn>
      </v-card-actions>

Enter fullscreen mode Exit fullscreen mode
  • Dentro del "script tag" de Vue, vamos a importar a Vuex para poder acceder al "client secret". Utilize su clave secreta pública de Stripe y la función window.Stripe() para obtener el Stripe Card Element. Su clave secreta pública debe almacenarse en el archivo .env; ¡nunca lo pongas directamente en el código! Una vez que obtengamos el Stripe Card Element, podemos modificar su apariencia Stripe appearance-api.

      // importe mapState y mapGetters para acceder
      // variables adicionales
      // script
      import store from '../store'

      const stripe = window.Stripe(
        process.env.VUE_APP_STRIPE_KEY
      )
      const options = {
        clientSecret: store.state.secret.clientSecret,
        // Personaliza tu Stripe theme.
        appearance: { theme: 'stripe' }
      }

      const elements = stripe.elements(options)

      const paymentElement = elements.create('payment')

Enter fullscreen mode Exit fullscreen mode
  • Montamos el Stripe Element usando la función "mounted" de Vue, esta va adentro de "export default".

      // export default
      mounted () {
        paymentElement.mount(this.$refs.paymentElement)
        paymentElement.on('change', (event) => {
          this.displayError(event)
        })
      },

Enter fullscreen mode Exit fullscreen mode
  • La Función displayError() le va a mostrar al cliente si su tarjeta de crédito tiene errores como fondos insuficientes entre otros.

      // methods
      displayError (event) {
        const displayError = document.getElementById(
          'error-message'
        )
        if (event.error) {
          displayError.textContent = event.error.message
        } else {
          displayError.textContent = ''
        }
      },

Enter fullscreen mode Exit fullscreen mode
  • Finalmente enviamos la transacción a través de la función Submit. Es importante destacar que "/thankyou/" es la dirección URL de nuestra última ruta. Esta se encuentra en el directorio bajo Thankyou.vue. Este Proyecto usa Vue Router para moverse fácilmente entre páginas. Use mapState para extraer propiedades del "state" y envialos con el objeto de "shipping".

      // methods
      async Submit () {
        this.loading = true
        const { error } = await stripe.confirmPayment({
          elements,
          confirmParams: {
            // return_url: ruta final del proyecto thankyou.vue
            return_url: 'http://localhost:8080/#/thankyou/',
            shipping: {
              address: {
                city: this.city,
                line1: this.address,
                postal_code: this.zipcode,
                state: this.state,
                country: 'USA'
              },
              name: `${this.first_name} ${this.last_name}`,
              phone: this.phone
            }
          }
        })
        if (error) {
          this.loading = false
          const messageContainer = document.querySelector(
            '#error-message'
          )
          messageContainer.textContent = error.message
        } else {
          // Redirección del cliente a return_url.
        }
      }

Enter fullscreen mode Exit fullscreen mode

4. Extracción de propiedades de Stripe.

  • Si necesitas extraer información adicional del cliente, debes hacerlo al final en la página de Thankyou.vue. A través de la función de javascript URLSearchParams(), extraemos el "payment_intent_client_secret" del URL, este será utilizado por la función de Stripe retrievePaymentIntent() para poder accesar al objeto de la transacción y enviar las propiedades a nuestro servidor. Una vez enviados los valores, rescatamos la respuesta y si todo está bien, vamos a usar las variables de entorno COMMIT_CHECKOUT y CLIENT_SECRET para borrar el "state".

      // mounted
      async mounted () {
        const stripe = window.Stripe(
          process.env.VUE_APP_STRIPE_KEY
        )
        const clientSecret = new URLSearchParams(
          window.location.search
        ).get(
          'payment_intent_client_secret'
        )
        const {
          paymentIntent, error
        } = await stripe.retrievePaymentIntent(
          clientSecret
        )
        if (error) {
          console.log(error)
          this.message = 'An error has ocurred'
        }
        if (paymentIntent.status === 'succeeded') {
          this.message = paymentIntent.status
          const payment_id = paymentIntent.id
          this.$store.dispatch('checkout', { payment_id })
            .catch((_err) => {
              this.loading = false
              const show = true
              const color = 'red darken-3'
              const text = 'An error has ocurred'
              this.$store.commit('cartSnack',
                {
                  show, color, text
                })
            })
        } else {
          this.message = paymentIntent.status
        }
      }

Enter fullscreen mode Exit fullscreen mode

      // actions
      async checkout ({ commit, state, getters }, payload) {
        const res = await axios.post('orders/order/', {
          order: {
            stripe_id: payload.payment_id,
            subtotal: getters.subTotal,
            total: getters.grandTotal,
            tax: state.secret.tax,
            cart: state.cart,
            rating: state.stars,
            first_name: state.user.first_name,
            last_name: state.user.last_name,
            email: state.user.email,
            phone: state.user.phone,
            address: state.user.address,
            city: state.user.city,
            state: state.user.state,
            zipcode: state.user.zipcode
          }
        })
        if (res.status === 200) {
          // Borrar el estado a excepción del usuario.
          commit('CHECKOUT_SUCCESS')
          commit('CLIENT_SECRET', {
            client_secret: null,
            tax: 0
          })
        }
      },

Enter fullscreen mode Exit fullscreen mode

      // mutations
      CHECKOUT_SUCCESS (state) {
        state.stars = []
        state.cart = []
      },

Enter fullscreen mode Exit fullscreen mode

Top comments (0)