154 lines
5.3 KiB
Markdown
154 lines
5.3 KiB
Markdown
|
|
# Развёртывание (Deploy)
|
|||
|
|
|
|||
|
|
## 1. Требования
|
|||
|
|
|
|||
|
|
- **Node.js 20+** и **npm 10+**
|
|||
|
|
- Доступ к серверу с веб-сервером (nginx / Apache / Caddy / IIS) или к статическому хостингу (Netlify, Vercel, GitHub Pages, S3 + CloudFront и т.п.)
|
|||
|
|
- HTTPS (обязательно — backend принимает только HTTPS, а Telegram QR не будет работать на http)
|
|||
|
|
|
|||
|
|
## 2. Сборка production-бандла
|
|||
|
|
|
|||
|
|
```powershell
|
|||
|
|
# в корне проекта
|
|||
|
|
npm ci # чистая установка зависимостей
|
|||
|
|
npm run build # production-сборка
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Результат окажется в папке `dist/qr-vitanova/browser/` — это и есть набор статических файлов, который надо опубликовать.
|
|||
|
|
|
|||
|
|
## 3. Конфигурация API
|
|||
|
|
|
|||
|
|
Эндпоинты заданы в `src/app/api.ts`:
|
|||
|
|
|
|||
|
|
- `FASTCHECK_API` — `https://api.fastcheck.store`
|
|||
|
|
- `QR_API` — `https://qr.vitanova.network:567/qr` (legacy, на текущих страницах не используется)
|
|||
|
|
|
|||
|
|
Имя Telegram-бота — в `src/app/pages/fastcheck-page/fastcheck-page.ts` (поле `telegramBot`, сейчас `DexarSupport_bot`).
|
|||
|
|
|
|||
|
|
## 4. Публикация статики
|
|||
|
|
|
|||
|
|
Скопируй содержимое `dist/qr-vitanova/browser/` в корень сайта.
|
|||
|
|
|
|||
|
|
### Важно: SPA-routing
|
|||
|
|
|
|||
|
|
У приложения два маршрута (`/` и `/new`), поэтому веб-сервер должен возвращать `index.html` для всех неизвестных путей, иначе обновление страницы на `/new` даст 404.
|
|||
|
|
|
|||
|
|
#### nginx
|
|||
|
|
|
|||
|
|
```nginx
|
|||
|
|
server {
|
|||
|
|
listen 443 ssl http2;
|
|||
|
|
server_name pay.example.com;
|
|||
|
|
|
|||
|
|
root /var/www/qr-vitanova;
|
|||
|
|
index index.html;
|
|||
|
|
|
|||
|
|
# SPA fallback
|
|||
|
|
location / {
|
|||
|
|
try_files $uri $uri/ /index.html;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# Кэш для статики
|
|||
|
|
location ~* \.(?:js|css|svg|woff2?|ico|png|jpg)$ {
|
|||
|
|
expires 30d;
|
|||
|
|
add_header Cache-Control "public, immutable";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# index.html — без кеша, чтобы быстро прилетал новый билд
|
|||
|
|
location = /index.html {
|
|||
|
|
add_header Cache-Control "no-cache";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ssl_certificate /etc/letsencrypt/live/pay.example.com/fullchain.pem;
|
|||
|
|
ssl_certificate_key /etc/letsencrypt/live/pay.example.com/privkey.pem;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
server {
|
|||
|
|
listen 80;
|
|||
|
|
server_name pay.example.com;
|
|||
|
|
return 301 https://$host$request_uri;
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### Apache (`.htaccess`)
|
|||
|
|
|
|||
|
|
```apache
|
|||
|
|
RewriteEngine On
|
|||
|
|
RewriteBase /
|
|||
|
|
RewriteRule ^index\.html$ - [L]
|
|||
|
|
RewriteCond %{REQUEST_FILENAME} !-f
|
|||
|
|
RewriteCond %{REQUEST_FILENAME} !-d
|
|||
|
|
RewriteRule . /index.html [L]
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### IIS (`web.config`)
|
|||
|
|
|
|||
|
|
```xml
|
|||
|
|
<configuration>
|
|||
|
|
<system.webServer>
|
|||
|
|
<rewrite>
|
|||
|
|
<rules>
|
|||
|
|
<rule name="SPA">
|
|||
|
|
<match url=".*" />
|
|||
|
|
<conditions logicalGrouping="MatchAll">
|
|||
|
|
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
|
|||
|
|
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
|
|||
|
|
</conditions>
|
|||
|
|
<action type="Rewrite" url="/index.html" />
|
|||
|
|
</rule>
|
|||
|
|
</rules>
|
|||
|
|
</rewrite>
|
|||
|
|
</system.webServer>
|
|||
|
|
</configuration>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 5. CORS на backend
|
|||
|
|
|
|||
|
|
`api.fastcheck.store` должен возвращать заголовки CORS, разрешающие домен фронта:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
Access-Control-Allow-Origin: https://pay.example.com
|
|||
|
|
Access-Control-Allow-Methods: GET, POST, DELETE, OPTIONS
|
|||
|
|
Access-Control-Allow-Headers: Content-Type, Authorization
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 6. Параметры запуска страницы
|
|||
|
|
|
|||
|
|
- `?session=<sessionID>` — необязательный, передаётся на `/new`, чтобы вставить `Authorization: {"sessionID": ...}` при `POST /fastcheck`.
|
|||
|
|
- `?return_url=<url>` — необязательный, на `/`. После успешного приёма фасчека (`POST /fastcheck` с `code`) страница редиректит на этот URL с параметрами `?fastcheck=...&status=ok` — это и есть merchant-callback.
|
|||
|
|
|
|||
|
|
Пример: `https://pay.example.com/?return_url=https://shop.example.com/order/42`
|
|||
|
|
|
|||
|
|
## 7. Деплой одной командой (пример через rsync)
|
|||
|
|
|
|||
|
|
```powershell
|
|||
|
|
npm run build
|
|||
|
|
rsync -az --delete dist/qr-vitanova/browser/ user@server:/var/www/qr-vitanova/
|
|||
|
|
ssh user@server "sudo systemctl reload nginx"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 8. Docker (опционально)
|
|||
|
|
|
|||
|
|
`Dockerfile`:
|
|||
|
|
|
|||
|
|
```dockerfile
|
|||
|
|
FROM node:20-alpine AS build
|
|||
|
|
WORKDIR /app
|
|||
|
|
COPY package*.json ./
|
|||
|
|
RUN npm ci
|
|||
|
|
COPY . .
|
|||
|
|
RUN npm run build
|
|||
|
|
|
|||
|
|
FROM nginx:1.27-alpine
|
|||
|
|
COPY --from=build /app/dist/qr-vitanova/browser/ /usr/share/nginx/html/
|
|||
|
|
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
|||
|
|
EXPOSE 80
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 9. Проверка после деплоя
|
|||
|
|
|
|||
|
|
1. Открой `https://pay.example.com/` — должна быть форма фастчека.
|
|||
|
|
2. Открой `https://pay.example.com/new` напрямую — должна открыться страница создания (не 404).
|
|||
|
|
3. В DevTools → Network проверь, что запросы к `https://api.fastcheck.store/...` идут без CORS-ошибок.
|
|||
|
|
4. Нажми «Оплатить» с заполненными полями — должен открыться popup с QR Telegram (`@DexarSupport_bot`).
|