DEV Community

Cover image for Construye un Sistema de Suscripciones con Vue js y Stripe.
Denisse Abreu
Denisse Abreu

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

Construye un Sistema de Suscripciones con Vue js y Stripe.

Hola 馃枑馃徏, en esta gu铆a, te mostrar茅 c贸mo crear un sistema de suscripci贸n con Vue.js y Stripe. Nuestro entorno de trabajo es Vue.js Options API, Vue Router y Express.js como administrador de backend. Para la UI/UX, estoy usando Vuetify. Si est谩 buscando la API de composici贸n de Vue 3 y la integraci贸n de TypeScript, consulte este turorial Cree un sistema de suscripci贸n con Vue 3, Vite y Stripe. Debido a lo extenso de este tutorial, les dejo el enlace a mi sitio web.

驴C贸mo construir un sistema de suscripci贸n con Stripe y Vue js? | CodingPR

Aprenda a crear un sistema de suscripci贸n con la API de opciones de Stripe y Vue js.

favicon codingpr.com

Si no tienes un proyecto, puedes copiar el m铆o aqu铆: vue-stripe-subscriptions

1. Configura Stripe.

Primero, configuremos nuestro entorno. Copie en su archivo env su clave publicable de stripe; puede encontrar esta clave en la secci贸n del desarrollador del Stripe 'Dashboard'. Crea dos productos en la secci贸n de productos del 'Dashboard', el plan B谩sico por cinco d贸lares y el plan Premium por diez. Copie los ID de los productos en el archivo env.


    VUE_APP_STRIPE_KEY=<YOUR-PUBLISHABLE-KEY>
    VUE_APP_BASIC_PLAN=<YOUR-BASIC-PLAN>
    VUE_APP_PREMIUM_PLAN=<YOUR-PREMIUM-PLAN>

Enter fullscreen mode Exit fullscreen mode
  • Una vez que haya abierto su cuenta con Stripe , copie la etiqueta del script en el encabezado de index.html.

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

Enter fullscreen mode Exit fullscreen mode

2. Integraci贸n.

Nuestro primer movimiento para integrar Stripe a Vue.js ser谩 realizando el evento 'on-click' cuando el cliente quiera suscribirse. Recopilaremos el correo electr贸nico y el nombre completo del cliente; en producci贸n, debe recopilar informaci贸n adicional, como la direcci贸n del cliente.


    <v-card-actions>
      <v-btn
        id="stripeBtn"
        class="mb-2"
        block
        :loading="loading"
        @click="Signup"
      >
        Sign Up
      </v-btn>
    </v-card-actions>

Enter fullscreen mode Exit fullscreen mode
  • En el siguiente bloque 'try and catch', enviamos, al backend, la informaci贸n personal del cliente que recopilamos del formulario de registro. Si recibimos una respuesta, empujaremos el plan 'view' con el id del cliente como par谩metro. Consulte los Vue Router Docs sobre c贸mo configurar el paso de par谩metros entre 'views'.

    // methods
    import PostService from '../post-service'

    async Signup() {
      const { email, fullname } = this
      try {
        const res = await PostService.createCust(
          email,
          fullname
        )

        if (res.data.customer) {
          this.$router.push({
            name:'Plan',
            params: {
              fullName: fullname,
              customerId: res.data.customer
            },
            props: true
          })
        }

      } catch (error) {
        this.alert1 = true;
        this.alertTxt = 'Error, Try again!'
      }
    }

Enter fullscreen mode Exit fullscreen mode
  • Cree un archivo en el src, el trabajo de este archivo es enviar solicitudes http al backend con Axios.

    import axios from 'axios';

    const url = 'http://localhost:3000/api/posts';

    class PostService {
      // Crea el cliente
      static async createCust(email, fullname) {
        const res = await axios.post(url, {
          email, fullname
        });
        return res;
      }
      // Crea la suscripci贸n
      static async createSubs(customerId, priceId) {
        const res = await axios.post(`${url}/subs`, {
          customerId, priceId
        });
        return res;
      }
      // Elimina la suscripci贸n
      static async delete(subscriptionId) {
        const res = await axios.post(`${url}/delete`, {
          subscriptionId,
        });
        return res;
      }
    }
    export default PostService;

Enter fullscreen mode Exit fullscreen mode
  • Despu茅s de recibir la respuesta del servidor con la identificaci贸n del cliente, Vue Router impulsar谩 el segundo paso; su cliente deber谩 elegir un plan. Cree dos botones con dos eventos de clic diferentes. Un bot贸n ser谩 para suscribirse al plan de cinco d贸lares y la otra al plan de diez d贸lares.

    <v-card-actions>
      <v-btn
        id="btnColor"
        :disabled="disabled"
        class="mx-auto mb-2"
        @click="subsPlan1"
      >
        Select
      </v-btn>
    </v-card-actions>
    <v-card-actions>
      <v-btn
        id="btnColor"
        :disabled="disabled2"
        class="mx-auto mb-2"
        @click="subsPlan2"
      >
        Seclect
      </v-btn>
    </v-card-actions>

Enter fullscreen mode Exit fullscreen mode
  • La funci贸n 'createSubscription' recibir谩 los par谩metros del plan que elija el cliente m谩s los 'props' del paso uno. Esta funci贸n enviar谩, al backend, el id del cliente y el id del precio y crear谩 la suscripci贸n; Si los datos de respuesta son buenos, el 'checkout view' se impulsar谩 con par谩metros.

    props: {
      fullName: String,
      customerId: String
    },

    data: () => ({
      disabled: false,
      disabled2: false,
      alert2: false,
      alertTxt: '',
    }),

    methods: {
      async createSubscription(priceId, price, plan) {
        const {fullName, customerId } = this
        try {
          const res = await PostService.createSubs(
            customerId,
            priceId,
          )

          if (res.data) {
            const subscriptionId = res.data.subscriptionId
            const clientSecret = res.data.clientSecret
            this.$router.push({
              name: 'Checkout',
              params: {
                fullName,
                price,
                plan,
                clientSecret,
                subscriptionId
              }
            })
          }

        } catch (err) {
          this.alert2 = true
          this.disabled = false
          this.alertTxt = 'An error has occurred. Try again later'
        }
      },

      async subsPlan1() {
        const priceId = process.env.VUE_APP_BASIC_PLAN
        const price = '5.00'
        const plan = 'Basic'
        this.disabled = true
        this.disabled2 = false
        await this.createSubscription(priceId, price, plan)
      },

      async subsPlan2() {
        const priceId = process.env.VUE_APP_PREMIUM_PLAN
        const price = '10.00'
        const plan = 'Premium'
        this.disabled2 = true
        this.disabled = false
        await this.createSubscription(priceId, price, plan)
      }
    }

Enter fullscreen mode Exit fullscreen mode

3. Montaje del Stipe Card Element.

Este es el 煤ltimo paso de la integraci贸n frontend, monta el elemento de la tarjeta y crea el 'Submit event'.


    <!-- Stripe Element-->
    <div
      ref="card"
      class="inputCard"
    />

    <!-- Mensajes de error en este espacio -->
    <div
      id="card-errors"
      role="alert"
    />
    <br>
    <v-alert
      v-model="alert"
      color="red"
      dense
      dismissible
      type="error"
    >
      <!-- alertTxt -->
    </v-alert>
    <v-btn
      id="stripeBtn"
      class="my-3"
      block
      :loading="loading"
      @click="Submit"
    >
      Pay with Stripe
    </v-btn>

Enter fullscreen mode Exit fullscreen mode
  • Utilice el secreto del cliente para acceder a la funci贸n de Stripe "confirmCardPayment". Dentro de esta funci贸n, env铆e el m茅todo de pago y la informaci贸n de facturaci贸n del cliente; Consulte la lista de par谩metros que puede enviar a stripe. Si la suscripci贸n es exitosa, se impulsar谩 el 'ThankYou view' con el id de la suscripci贸n como par谩metro.

    import PostService from '../post-service'

    const stripe = window.Stripe(process.env.VUE_APP_STRIPE_KEY)

    // Cree una instancia del Stripe Elements.
    const elements = stripe.elements()
    const style = {
      base: {
        color: '#32325d',
        fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
        fontSmoothing: 'antialiased',
        fontSize: '16px',
        '::placeholder': {
          color: '#aab7c4',
        },
      },
      invalid: {
        color: '#fa755a',
        iconColor: '#fa755a',
      },
    };

    const card = elements.create('card', { style: style })

    export default {
      props: {
        fullName: String,
        price: String,
        plan: String,
        clientSecret: String,
        subscriptionId: String
      },

      mounted() {
        card.mount(this.$refs.card)

        card.on('change', (event) => {
          this.displayError(event)
        })
      },

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

        async Submit() {
          this.loading = true
          const { clientSecret, fullName, alert, alertTxt, loading } = this
          const result = await stripe.confirmCardPayment(clientSecret, {
            payment_method: {
              type: 'card',
              card: card,
              billing_details: {
                name: fullName,
              }
            }
          })

          if (result.error) {
            alert = true
            alertTxt = result.error.message
            loading = false
          } else {
            // Pago de suscripci贸n exitoso
            // La suscripci贸n se activa autom谩ticamente al momento del pago.
            this.$router.push({
              name: 'ThankYou',
              params: {
                subscriptionId: this.subscriptionId
              }
            })
          }
        }
      }
    }

Enter fullscreen mode Exit fullscreen mode

Chequea el backend aqu铆: Sistema de suscripci贸n con Stripe y Express

Top comments (0)