Здравствуйте 🖐🏼, в этом руководстве я покажу вам, как создать систему подписки с помощью Vue.js и Stripe. Наша рабочая среда — это Vue.js Options API, Vue Router и Express.js в качестве бэкенд-менеджера. Для UI/UX я использую Vuetify. Если вы ищете интеграцию Vue 3 Composition API и TypeScript, посмотрите мой репозиторий Vue 3 Stripe Subscriptions. Из-за обширности этого руководства я оставляю ссылку на мой сайт; там лучше визуализация.

Создание системы подписки с помощью Stripe и Vue js | CodingPR
Узнайте, как построить систему подписки с помощью Stripe и Vue js Options API.

Если у вас нет проекта, вы можете скопировать мой здесь:
vue-stripe-subscriptions .
1. Настройка Stripe.
Сначала давайте настроим наше окружение. Скопируйте в свой env-файл публикуемый ключ из панели инструментов stripe; вы можете найти этот ключ в разделе разработчика панели инструментов. Создайте два продукта в разделе продуктов панели инструментов: базовый план за пять долларов и премиум-план за десять. Скопируйте идентификаторы продуктов в файл env.
VUE_APP_STRIPE_KEY=<YOUR-PUBLISHABLE-KEY>
VUE_APP_BASIC_PLAN=<YOUR-BASIC-PLAN>
VUE_APP_PREMIUM_PLAN=<YOUR-PREMIUM-PLAN>
- После того как вы открыли счет в Stripe, скопируйте тег script в head файла index.html.
<head>
<script src="https://js.stripe.com/v3/"></script>
</head>
2. Интеграция.
Наш первый шаг по интеграции Stripe в Vue.js — это создание события on-click, когда клиент хочет подписаться на ваш сервис подписки. Мы собираем email и полное имя клиента; в продакшене вы должны собирать дополнительную информацию, например, адрес клиента.
<v-card-actions>
<v-btn
id="stripeBtn"
class="mb-2"
block
:loading="loading"
@click="Signup"
>
Sign Up
</v-btn>
</v-card-actions>
- В этом блоке try and catch мы отправляем в бэкенд личные данные клиента, которые мы собрали в форме регистрации. Если мы получим ответ, то выведем на экран представление плана с идентификатором клиента в качестве параметра. О том, как настроить передачу параметров между представлениями, читайте в документации Vue Router.
// 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!'
}
}
- Создайте файл в корне папки src, задача этого файла — отправлять http-запросы на бэкенд с помощью Axios.
import axios from 'axios';
const url = 'http://localhost:3000/api/posts';
class PostService {
// Create customer
static async createCust(email, fullname) {
const res = await axios.post(url, {
email, fullname
});
return res;
}
// Create subscription
static async createSubs(customerId, priceId) {
const res = await axios.post(`${url}/subs`, {
customerId, priceId
});
return res;
}
// Delete subscription
static async delete(subscriptionId) {
const res = await axios.post(`${url}/delete`, {
subscriptionId,
});
return res;
}
}
export default PostService;
- После получения ответа от сервера с идентификатором клиента, Vue Router перейдет ко второму шагу; ваш клиент должен выбрать тарифный план. Сделайте две кнопки с двумя разными событиями при нажатии. Одна из них предназначена для подписки на пятидолларовый план, а другая — на десятидолларовый.
<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>
- Функция создания подписки получит параметры плана, который выберет клиент, плюс реквизиты из первого шага. Эта функция отправит в бэкенд идентификатор клиента и идентификатор цены и создаст подписку; если данные ответа будут хорошими, то будет выведено представление оформления заказа с параметрами.
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)
}
}
3. Монтаж элемента карточки.
Это последний шаг интеграции с фронтендом, смонтируйте элемент карточки и создайте событие отправки.
<!-- Stripe Element-->
<div
ref="card"
class="inputCard"
/>
<!-- Error messages in this element -->
<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>
- Используйте секрет клиента для доступа к функции Stripe «подтвердить оплату картой». Внутри этой функции отправьте метод оплаты и информацию о биллинге клиента; проверьте список параметров, которые вы можете отправить в Stripe. Если подписка прошла успешно, выведите благодарственное представление с идентификатором подписки в качестве параметра.
import PostService from '../post-service'
const stripe = window.Stripe(process.env.VUE_APP_STRIPE_KEY)
// Create an instance of 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 {
// Successful subscription payment
// The subscription automatically becomes active upon payment.
this.$router.push({
name: 'ThankYou',
params: {
subscriptionId: this.subscriptionId
}
})
}
}
}
}
Ознакомьтесь с бэкендом здесь: Система подписки с Stripe и Express