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.
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>
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>
- 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>
// 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')
}
}
- 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')
}
},
// vuex mutations
CLIENT_SECRET (state, payload) {
const secret = state.secret
secret.clientSecret = payload.client_secret
secret.tax = payload.tax
},
- 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: []
},
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>
- 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')
- 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)
})
},
- 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 = ''
}
},
- 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.
}
}
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
}
}
// 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
})
}
},
- Borra el 'state' cuando el pago se haya completado. Para integrar Stripe en la parte del servidor, visite este blog: ¿Cómo conectar Stripe a Django Rest Framework?
// mutations
CHECKOUT_SUCCESS (state) {
state.stars = []
state.cart = []
},
Top comments (0)