Для отслеживания оплаты и сроков истечения подписки в системе Stripe, вам нужно настроить соответствующие события и интегрировать клиентскую и серверную части приложения. Ниже приведен план и пример кода, который поможет реализовать процесс подписки с использованием Stripe.
### Структура проекта
- **Клиентская часть (React)**: Отправка запросов на сервер для создания и управления подписками.
- **Серверная часть (NestJS)**: Обработка логики создания, управления подписками и обработки вебхуков от Stripe.
### Серверная часть на NestJS
1. **Установите необходимые пакеты:**
```bash
npm install @nestjs/common @nestjs/core @nestjs/platform-express stripe
```
2. **Создайте сервис для работы с Stripe:**
```typescript
// stripe.service.ts
import { Injectable } from '@nestjs/common';
import Stripe from 'stripe';
@Injectable()
export class StripeService {
private stripe: Stripe;
constructor() {
this.stripe = new Stripe(process.env.STRIPE_SECRET_KEY, {
apiVersion: '2020-08-27',
});
}
async createSubscription(customerId: string, priceId: string) {
const subscription = await this.stripe.subscriptions.create({
customer: customerId,
items: [{ price: priceId }],
expand: ['latest_invoice.payment_intent'],
});
return subscription;
}
async handleWebhook(payload: any) {
switch (payload.type) {
case 'invoice.payment_succeeded':
// Обработка успешной оплаты
break;
case 'invoice.payment_failed':
// Обработка неудачной оплаты
break;
case 'customer.subscription.updated':
// Обработка обновления подписки
break;
}
}
}
```
3. **Создайте контроллер для обработки запросов:**
```typescript
// stripe.controller.ts
import { Controller, Post, Body, Req, Res } from '@nestjs/common';
import { StripeService } from './stripe.service';
import { Request, Response } from 'express';
@Controller('stripe')
export class StripeController {
constructor(private readonly stripeService: StripeService) {}
@Post('subscribe')
async subscribe(@Body() body: { customerId: string; priceId: string }) {
return await this.stripeService.createSubscription(body.customerId, body.priceId);
}
@Post('webhook')
async webhook(@Req() req: Request, @Res() res: Response) {
const payload = req.body;
await this.stripeService.handleWebhook(payload);
res.status(200).send('Received');
}
}
```
4. **Настройте маршрутизацию и обработку вебхуков в `main.ts`:**
```typescript
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import * as express from 'express';
import * as bodyParser from 'body-parser';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.use(bodyParser.json({ verify: (req, res, buf) => { req.rawBody = buf; } }));
await app.listen(3000);
}
bootstrap();
```
### Клиентская часть на React
1. **Установите необходимые библиотеки:**
```bash
npm install @stripe/react-stripe-js @stripe/stripe-js axios
```
2. **Создайте компонент для обработки подписки:**
```jsx
// SubscriptionForm.js
import React, { useState } from 'react';
import { loadStripe } from '@stripe/stripe-js';
import axios from 'axios';
const stripePromise = loadStripe('your-publishable-key-here');
const SubscriptionForm = () => {
const [loading, setLoading] = useState(false);
const handleSubscribe = async () => {
setLoading(true);
const stripe = await stripePromise;
try {
const response = await axios.post('http://localhost:3000/stripe/subscribe', {
customerId: 'customer-id',
priceId: 'price-id',
});
// Обработка успешной подписки
console.log(response.data);
} catch (error) {
console.error('Error subscribing:', error);
} finally {
setLoading(false);
}
};
return (
<button onClick={handleSubscribe} disabled={loading}>
{loading ? 'Loading...' : 'Subscribe'}
</button>
);
};
export default SubscriptionForm;
```
### Об