Перейти до вмісту

� Модуль Платежів та Інтеграція WayForPay (`PaymentsModule`)

📌 Огляд та Архітектура

Модуль PaymentsModule реалізує повний життєвий цикл платіжного шлюзу WayForPay (включаючи тестовий Sandbox та бойовий Live режими), генерацію інвойсів, валідацію HMAC-MD5 підписів, обробку вебхуків, автоматичне продовження ліцензій та повний фінансовий облік транзакцій.


🏛 Архітектурний Стек & CQRS Розподіл

sequenceDiagram
autonumber
participant C as Client (Desktop / Web)
participant API as PaymentsController
participant CQRS as Command / Query Bus
participant WFP as WayForPay Gateway
participant DB as PostgreSQL (PaymentTransaction)
participant Lic as LicensesModule
C->>API: POST /api/payments/checkout { planCode, billingInterval }
API->>CQRS: execute(CreatePaymentInvoiceCommand)
CQRS->>DB: create PaymentTransaction (status: PENDING)
CQRS->>API: return CheckoutResponseDto (form fields + HMAC-MD5 signature)
API->>C: return checkout form params & invoice URL
C->>WFP: Submit payment form
WFP-->>API: POST /api/payments/wayforpay/webhook (transactionStatus: Approved)
API->>CQRS: execute(HandleWayForPayWebhookCommand)
CQRS->>DB: update PaymentTransaction (status: APPROVED, cardPan, authCode)
CQRS->>Lic: execute(SelectTariffPlanCommand) (30 days monthly / 365 days yearly)
CQRS->>API: return WayForPay Accept Response (orderReference + accept signature)
API-->>WFP: 200 OK Accept JSON

🔐 Алгоритм Розрахунку Підписів (HMAC-MD5)

1. Формування підпису запиту на оплату (merchantSignature):

const signString = [
merchantAccount,
merchantDomainName,
orderReference,
orderDate,
amount,
currency,
...productName,
...productCount,
...productPrice,
].join(';');
const signature = crypto
.createHmac('md5', merchantSecretKey)
.update(signString, 'utf8')
.digest('hex');

2. Валідація підпису Webhook (merchantSignature):

const webhookSignString = [
merchantAccount,
orderReference,
amount,
currency,
authCode || '',
cardPan || '',
transactionStatus,
reasonCode || '',
].join(';');
const expectedSignature = crypto
.createHmac('md5', merchantSecretKey)
.update(webhookSignString, 'utf8')
.digest('hex');

3. Формування відповіді підтвердження (accept):

const time = Math.floor(Date.now() / 1000);
const acceptSignString = [orderReference, 'accept', time].join(';');
const acceptSignature = crypto
.createHmac('md5', merchantSecretKey)
.update(acceptSignString, 'utf8')
.digest('hex');
return {
orderReference,
status: 'accept',
time,
signature: acceptSignature,
};

📊 Доступні Ендпоінти

МетодЕндпоінтОписДоступ
POST/api/payments/checkoutСтворення інвойсу та параметрів форми WayForPayАвторизований користувач
POST/api/payments/wayforpay/webhookПрийом та валідація вебхуку результату оплатиПублічний (перевірка HMAC)
POST/api/payments/simulate-sandbox-webhookСимуляція Sandbox оплати (Approved/Declined)Авторизований користувач
GET/api/payments/transactionsСписок транзакцій з пагінацією та пошукомТільки ADMIN / SUPER_ADMIN
GET/api/payments/statsФінансова аналітика (дохід, конверсія, середній чек)Тільки ADMIN / SUPER_ADMIN
GET/api/payments/settingsНалаштування платіжних системТільки ADMIN / SUPER_ADMIN
PATCH/api/payments/settings/:providerОновлення ключів мерчанта, домену та Sandbox режимуТільки ADMIN / SUPER_ADMIN
GET/api/payments/my-transactionsІсторія оплат поточного користувачаАвторизований користувач