DEV Community

Cover image for 驴C贸mo Conectar Stripe a Vue?
Denisse Abreu
Denisse Abreu

Posted on • Updated 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 Vue.js? | CodingPR

Integraci贸n del sistema de pagos de Stripe a su proyecto Vuejs.

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

Discussion (0)