---
title: "Інтеграція платіжних шлюзів"
description: "Інтегруйте обробку платежів з WayForPay, Stripe та локальними постачальниками"
locale: "uk"
---
# Інтеграція платіжних шлюзів

> **Info**
> **Філософія платежів Ring**: "Монетизація має покращувати цінність, а не створювати бар'єри." Увімкніть кілька методів оплати, зберігаючи транзакції безперешкодними та безпечними.

Ring підтримує кілька платіжних шлюзів одразу з коробки, з WayForPay як стандартним для українських та європейських ринків. Цей посібник покаже вам, як:

- Конфігурувати платіжні шлюзи для вашого регіону
- Налаштувати підписки та одноразові платежі
- Інтегрувати з ринком та токенними системами Ring
- Обробляти мультивалютні транзакції
- Впровадити безпечні платіжні потоки

## Огляд архітектури платежів

### Підтримувані шлюзи

| Шлюз | Регіони | Функції | Комісії |
|---------|---------|----------|------|
| **WayForPay** | Україна, Європа | Карти, Apple Pay, Google Pay, Крипто | 3.5% + €0.25 |
| **Stripe** | Глобально | 135+ валют, розширені інтеграції | 2.9% + €0.30 |
| **PayPal** | Глобально | PayPal рахунки, захист покупця | 2.9% + €0.30 |
| **Локальні постачальники** | Країна-специфічні | Локальні методи оплати | Варіюється |

### Типи платежів

**1. Транзакції ринку**
- Покупки продуктів
- Бронювання послуг
- Комісійні збори

**2. Платежі підписки**
- Преміум функції
- Рівні членства
- Нагороди стейкінгу токенів

**3. Токенні транзакції**
- Купівлі токенів RING
- Розрахунки смарт-контрактів
- Автоматизовані виплати

**4. Платіжні збори платформи**
- Лістинги можливостей
- Верифікація продавців
- Використання API

## Інтеграція WayForPay (Стандартна)

> **Success**
> **Рекомендовано для**: Українських бізнесів, європейських операцій, крипто-дружніх платформ

### Процес налаштування

  
**Створіть рахунок WayForPay:**

    1. Відвідайте [wayforpay.com](https://wayforpay.com)
    2. Зареєструйтеся як мерчант
    3. Завершіть KYC верифікацію
    4. Отримайте облікові дані мерчанта

  
**Налаштуйте в Ring:**

    Конфігурація WayForPay

{`WAYFORPAY_MERCHANT_ID=your_merchant_id
    WAYFORPAY_SECRET_KEY=your_secret_key
    WAYFORPAY_TEST_MODE=true  # Встановіть false для продакшену`}

  
**Налаштуйте вебхуки:**

    Налаштуйте ці URL вебхуків у вашій панелі WayForPay:

    ```
    Success: https://yourdomain.com/api/payments/wayforpay/success
    Failure: https://yourdomain.com/api/payments/wayforpay/failure
    Callback: https://yourdomain.com/api/payments/wayforpay/callback
    ```

  
**Протестуйте інтеграцію:**

    Протестуйте з WayForPay sandbox

{`npm run test:payments -- --gateway wayforpay`}

### Реалізація API WayForPay

  
**Створіть сервіс платежів:**

    // lib/payments/wayforpay/service.ts

{`export class WayForPayService {
      private merchantId: string;
      private secretKey: string;

      constructor() {
        this.secretKey = process.env.WAYFORPAY_SECRET_KEY!;
      }

      async createPayment(orderData: OrderData): Promise {
        const signature = this.generateSignature(orderData);

        const paymentData = {
          merchantAccount: this.merchantId,
          merchantDomainName: process.env.NEXT_PUBLIC_APP_URL,
          orderReference: orderData.id,
          orderDate: Math.floor(Date.now() / 1000),
          amount: orderData.amount,
          currency: orderData.currency,
          productName: orderData.items.map(item => item.name),
          productCount: orderData.items.map(item => item.quantity),
          productPrice: orderData.items.map(item => item.price),
          serviceUrl: `${process.env.NEXT_PUBLIC_APP_URL}/api/payments/wayforpay/callback`,
          returnUrl: `${process.env.NEXT_PUBLIC_APP_URL}/payment/success`,
        };

        const response = await fetch('https://api.wayforpay.com/api', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            apiVersion: 1,
            ...paymentData,
            merchantSignature: signature,
          }),
        });

        return response.json();
      }

      private generateSignature(data: any): string {
        const values = [
          this.merchantId,
          data.orderReference,
          data.amount,
          data.currency,
          this.secretKey,
        ];

        return crypto.createHash('md5').update(values.join(';')).digest('hex');
      }
    }`}

  
**Обробіть зворотні виклики платежів:**

    // app/api/payments/wayforpay/callback/route.ts

{`export async function POST(request: Request) {
      const callbackData = await request.json();

      // Перевірити підпис
      const isValid = verifyWayForPaySignature(callbackData);

      if (!isValid) {
        return Response.json({ error: 'Invalid signature' }, { status: 400 });
      }

      // Обробити платіж залежно від статусу
      switch (callbackData.transactionStatus) {
        case 'Approved':
          await processSuccessfulPayment(callbackData);
          break;
        case 'Declined':
          await processFailedPayment(callbackData);
          break;
        case 'Refunded':
          await processRefund(callbackData);
          break;
      }

      return Response.json({ status: 'ok' });
    }`}

## Інтеграція Stripe (Глобальна)

> **Success**
> **Рекомендовано для**: Міжнародних платформ, високотрафікових транзакцій, розширених функцій

### Процес налаштування

  
**Створіть рахунок Stripe:**

    1. Відвідайте [stripe.com](https://stripe.com)
    2. Завершіть бізнес верифікацію
    3. Увімкніть бажані методи оплати
    4. Отримайте API ключі з панелі

  
**Встановіть Stripe SDK:**

    
{`npm install stripe`}

  
**Налаштуйте середовище:**

    
{`STRIPE_SECRET_KEY=sk_live_...
    STRIPE_WEBHOOK_SECRET=whsec_...`}

  
**Налаштуйте вебхуки:**

    Налаштуйте endpoint вебхука в панелі Stripe:

    ```
    Endpoint URL: https://yourdomain.com/api/payments/stripe/webhook
    Події: payment_intent.succeeded, payment_intent.payment_failed
    ```

### Реалізація Stripe

  
**Створіть сервіс Stripe:**

    // lib/payments/stripe/service.ts

{`import Stripe from 'stripe';

    export class StripePaymentService {
      private stripe: Stripe;

      constructor() {
        this.stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
          apiVersion: '2023-10-16',
        });
      }

      async createPaymentIntent(amount: number, currency: string, metadata?: any) {
        const paymentIntent = await this.stripe.paymentIntents.create({
          amount: Math.round(amount * 100), // Конвертувати в центи
          currency: currency.toLowerCase(),
          automatic_payment_methods: {
            enabled: true,
          },
          metadata: {
            integration_check: 'accept_a_payment',
            ...metadata,
          },
        });

        return {
          clientSecret: paymentIntent.client_secret,
          paymentIntentId: paymentIntent.id,
        };
      }

      async confirmPayment(paymentIntentId: string) {
        const paymentIntent = await this.stripe.paymentIntents.retrieve(paymentIntentId);

        if (paymentIntent.status === 'succeeded') {
          await processSuccessfulPayment({
            id: paymentIntentId,
            amount: paymentIntent.amount / 100,
            currency: paymentIntent.currency,
            metadata: paymentIntent.metadata,
          });
        }
      }
    }`}

  
**Frontend форма оплати:**

    // components/payments/stripe-checkout.tsx

{`'use client';

    import { loadStripe } from '@stripe/stripe-js';
    import { Elements, CardElement, useStripe, useElements } from '@stripe/react-stripe-js';

    const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY!);

    export function StripeCheckoutForm({ amount, onSuccess }) {
      const stripe = useStripe();
      const elements = useElements();

      const handleSubmit = async (event) => {
        event.preventDefault();

        const { error, paymentIntent } = await stripe.confirmCardPayment(
          clientSecret,
          {
            payment_method: {
              card: elements.getElement(CardElement),
            },
          }
        );

        if (!error) {
          onSuccess(paymentIntent);
        }
      };

      return (
        
          
          Pay ${amount}
        
      );
    }`}

## Підтримка мульти-шлюзів

### Роутер шлюзів

  
**Створіть роутер шлюзів:**

    // lib/payments/gateway-router.ts

{`export class PaymentGatewayRouter {
      private gateways = new Map<string, PaymentGateway>();

      constructor() {
        this.gateways.set('wayforpay', new WayForPayService());
        this.gateways.set('stripe', new StripePaymentService());
        this.gateways.set('paypal', new PayPalService());
      }

      getGateway(userLocation: string, paymentMethod: string): PaymentGateway {
        // Направляти залежно від локації та методу оплати
        if (userLocation === 'UA' && paymentMethod === 'card') {
          return this.gateways.get('wayforpay')!;
        }

        if (paymentMethod === 'paypal') {
          return this.gateways.get('paypal')!;
        }

        // За замовчуванням Stripe для міжнародних
        return this.gateways.get('stripe')!;
      }

      async processPayment(orderData: OrderData): Promise {
        const gateway = this.getGateway(orderData.userLocation, orderData.paymentMethod);
        return gateway.processPayment(orderData);
      }
    }`}

  
**Географічна маршрутизація:**

    // lib/payments/geo-routing.ts

{`export const paymentRoutingRules = {
      UA: {
        primary: 'wayforpay',
        fallback: 'stripe',
        supported: ['card', 'apple_pay', 'google_pay', 'crypto'],
      },
      US: {
        primary: 'stripe',
        fallback: 'paypal',
        supported: ['card', 'apple_pay', 'google_pay', 'paypal'],
      },
      EU: {
        primary: 'stripe',
        fallback: 'wayforpay',
        supported: ['card', 'apple_pay', 'google_pay', 'sepa', 'sofort'],
      },
      default: {
        primary: 'stripe',
        fallback: 'paypal',
        supported: ['card', 'paypal'],
      },
    };

    export function getOptimalGateway(countryCode: string, paymentType: string) {
      const rules = paymentRoutingRules[countryCode] || paymentRoutingRules.default;

      if (rules.supported.includes(paymentType)) {
        return rules.primary;
      }

      return rules.fallback;
    }`}

## Інтеграція токенних платежів

### Платежі токенами RING

  
**Інтеграція смарт-контрактів:**

    // lib/payments/token-payments.ts

{`export class TokenPaymentService {
      async transferTokens(
        from: string,
        to: string,
        amount: number,
        tokenAddress: string
      ) {
        // Для токенів RING на блокчейні
        const contract = new ethers.Contract(tokenAddress, ERC20_ABI, signer);

        const tx = await contract.transfer(to, ethers.parseEther(amount.toString()));
        await tx.wait();

        return tx.hash;
      }

      async transferViaBridge(
        from: string,
        to: string,
        amount: number,
        fromChain: string,
        toChain: string
      ) {
        // Крос-чейн трансфери токенів
        const bridgeTx = await this.bridgeService.bridgeTokens({
          fromChain,
          toChain,
          tokenAddress: RING_TOKEN_ADDRESS,
          amount: ethers.parseEther(amount.toString()),
          recipient: to,
        });

        return bridgeTx.hash;
      }
    }`}

  
**Потік токенних платежів:**

    // Для лістингів можливостей, оплачених у RING

{`export async function payForOpportunityListing(
      opportunityId: string,
      amount: number,
      userWallet: string
    ) {
      // Перевірити баланс RING користувача
      const balance = await tokenService.getBalance(userWallet);

      if (balance < amount) {
        throw new Error('Insufficient RING balance');
      }

      // Трансферувати RING до скарбниці платформи
      const txHash = await tokenService.transfer(
        userWallet,
        PLATFORM_TREASURY,
        amount,
        RING_TOKEN_ADDRESS
      );

      // Створити лістинг можливості
      await opportunityService.createListing({
        id: opportunityId,
        paymentTx: txHash,
        status: 'active',
      });

      return { success: true, txHash };
    }`}

## Управління підписками

### Рекурентні платежі

  
**Налаштуйте плани підписки:**

    // lib/payments/subscriptions.ts

{`export const subscriptionPlans = {
      basic: {
        name: 'Basic',
        price: 9.99,
        currency: 'USD',
        interval: 'month',
        features: ['basic_listings', 'email_support'],
      },
      premium: {
        name: 'Premium',
        price: 29.99,
        currency: 'USD',
        interval: 'month',
        features: ['unlimited_listings', 'priority_support', 'analytics'],
      },
      enterprise: {
        name: 'Enterprise',
        price: 99.99,
        currency: 'USD',
        interval: 'month',
        features: ['white_label', 'api_access', 'dedicated_support'],
      },
    };`}

  
**Реалізація підписки Stripe:**

    
{`async createSubscription(userId: string, planId: string) {
        const plan = subscriptionPlans[planId];
        const priceId = await this.getOrCreatePriceId(plan);

        const session = await this.stripe.checkout.sessions.create({
          mode: 'subscription',
          payment_method_types: ['card'],
          line_items: [{
            price: priceId,
            quantity: 1,
          }],
          success_url: `${process.env.NEXT_PUBLIC_APP_URL}/subscription/success`,
          cancel_url: `${process.env.NEXT_PUBLIC_APP_URL}/subscription/cancel`,
          client_reference_id: userId,
          metadata: {
            planId,
          },
        });

        return { sessionId: session.id, url: session.url };
      }

      async handleWebhook(event: Stripe.Event) {
        switch (event.type) {
          case 'customer.subscription.created':
            await this.activateSubscription(event.data.object);
            break;
          case 'customer.subscription.updated':
            await this.updateSubscription(event.data.object);
            break;
          case 'customer.subscription.deleted':
            await this.cancelSubscription(event.data.object);
            break;
        }
      }
    }`}

## Безпека та відповідність

### PCI відповідність

  
**Стратегія токенізації:**

    
{`// Ніколи не зберігати деталі картки - використовувати токени
export class SecurePaymentService {
      async tokenizeCard(cardDetails: CardDetails): Promise {
        // Надіслати до процесора платежів для токенізації
        const tokenResponse = await this.gateway.tokenize(cardDetails);

        // Зберігати тільки токен
        await this.storeToken(tokenResponse.token, {
          last4: cardDetails.number.slice(-4),
          brand: cardDetails.brand,
          expiryMonth: cardDetails.expiryMonth,
          expiryYear: cardDetails.expiryYear,
        });

        return tokenResponse.token;
      }

      async chargeToken(token: string, amount: number): Promise {
        // Списувати використовуючи токен - деталі картки не торкаються
        return this.gateway.chargeToken(token, amount);
      }
    }`}

  
**Реалізація 3D Secure:**

    
{`export async function process3DSecurePayment(orderData: OrderData) {
// Перевірити, чи потрібен 3D Secure
      const requires3DS = await this.assess3DSRequirement(orderData);

      if (requires3DS) {
        // Перенаправити на аутентифікацію 3D Secure
        const authUrl = await this.initiate3DSAuthentication(orderData);

        return {
          status: 'requires_authentication',
          authUrl,
        };
      }

      // Обробити звичайний платіж
      return this.processStandardPayment(orderData);
    }`}

### Запобігання шахрайству

  
**Оцінка ризику:**

    // lib/payments/fraud-prevention.ts

{`export class FraudPreventionService {
      async assessPaymentRisk(paymentData: PaymentData): Promise {
        const riskFactors = await Promise.all([
          this.checkAmountAnomaly(paymentData.amount, paymentData.userHistory),
          this.checkGeographicAnomaly(paymentData.location, paymentData.userProfile),
          this.checkVelocityAnomaly(paymentData.userId, paymentData.timeframe),
          this.checkDeviceFingerprint(paymentData.deviceFingerprint),
        ]);

        const totalRisk = riskFactors.reduce((sum, factor) => sum + factor.score, 0);

        return {
          score: totalRisk,
          level: totalRisk > 80 ? 'high' : totalRisk > 50 ? 'medium' : 'low',
          factors: riskFactors,
        };
      }

      async handleHighRiskPayment(paymentData: PaymentData, riskScore: RiskScore) {
        // Потрібна додаткова верифікація
        await this.requestAdditionalVerification(paymentData.userId);

        // Логувати для ручного огляду
        await this.logSuspiciousActivity(paymentData, riskScore);
      }
    }`}

  
**Обробка чарджбеків:**

    
{`export async function handleChargeback(chargebackData: ChargebackData) {
// Повідомити зацікавлені сторони
      await this.notifyMerchant(chargebackData);

      // Оновити статус платежу
      await this.updatePaymentStatus(chargebackData.paymentId, 'disputed');

      // Логувати деталі диспуту
      await this.logChargeback(chargebackData);

      // Ескалювати, якщо виявлено патерн
      const pattern = await this.detectChargebackPattern(chargebackData.merchantId);
      if (pattern.isProblematic) {
        await this.escalateToRiskTeam(chargebackData, pattern);
      }
    }`}

## Підтримка мультивалютності

### Конвертація валют

  
**Курс валют у реальному часі:**

    // lib/payments/currency-exchange.ts

{`export class CurrencyExchangeService {
      private exchangeRates = new Map<string, number>();

      async updateExchangeRates() {
        // Отримати з надійного API (наприклад, Fixer, Open Exchange Rates)
        const response = await fetch(`${process.env.EXCHANGE_RATE_API_URL}?base=USD`);

        const data = await response.json();

        // Кешувати курси на 1 годину
        this.exchangeRates = new Map(Object.entries(data.rates));
        await this.cacheRates(this.exchangeRates, 3600);
      }

      convertAmount(amount: number, fromCurrency: string, toCurrency: string): number {
        const usdAmount = amount / this.exchangeRates.get(fromCurrency)!;
        return usdAmount * this.exchangeRates.get(toCurrency)!;
      }
    }`}

  
**Оплата у валюті користувача:**

    
{`amount: number,
      currency: string,
      userCountry: string
    ) {
      // Отримати бажану валюту користувача
      const userCurrency = this.getUserPreferredCurrency(userCountry);

      // Конвертувати, якщо необхідно
      const convertedAmount = currency !== userCurrency
        ? await this.currencyService.convertAmount(amount, currency, userCurrency)
        : amount;

      // Створити платіж у валюті користувача
      return this.createPayment({
        amount: convertedAmount,
        currency: userCurrency,
        originalAmount: amount,
        originalCurrency: currency,
      });
    }`}

## Тестування та моніторинг

### Тестування платежів

  
**Протестувати потоки платежів:**

    // lib/testing/payment-tests.ts

{`export class PaymentTestSuite {
      async testFullPaymentFlow() {
        // Протестувати карткові платежі
        await this.testCardPayment('4242424242424242', 'success'); // Stripe тестова картка
        await this.testCardPayment('4000000000000002', 'decline'); // Відхилена

        // Протестувати WayForPay
        await this.testWayForPayPayment(testOrderData);

        // Протестувати підписки
        await this.testSubscriptionCreation();
        await this.testSubscriptionCancellation();

        // Протестувати refunds
        await this.testRefundProcessing();
      }

      async testCardPayment(cardNumber: string, expectedResult: string) {
        const paymentData = {
          amount: 10.00,
          currency: 'USD',
          card: { number: cardNumber, /* ... */ },
        };

        const result = await this.paymentService.processPayment(paymentData);

        assert.equal(result.status, expectedResult);
      }
    }`}

  
**Інтеграційне тестування:**

    Запустити інтеграційні тести платежів Протестувати конкретний шлюз Тестування навантаження

{`npm run test:integration -- --suite payments

    npm run test:payments -- --gateway stripe --env sandbox

    npm run test:load -- --endpoint /api/payments --concurrency 100`}

### Аналітика платежів

  
**Панель доходів:**

    // lib/analytics/payment-analytics.ts

{`export class PaymentAnalytics {
      async getRevenueMetrics(timeframe: string) {
        const payments = await this.getPaymentsInTimeframe(timeframe);

        return {
          totalRevenue: payments.reduce((sum, p) => sum + p.amount, 0),
          averageOrderValue: payments.reduce((sum, p) => sum + p.amount, 0) / payments.length,
          conversionRate: await this.calculateConversionRate(timeframe),
          paymentMethodBreakdown: this.groupByPaymentMethod(payments),
          geographicRevenue: this.groupByCountry(payments),
          refundRate: await this.calculateRefundRate(timeframe),
        };
      }

      async getFraudMetrics() {
        return {
          blockedPayments: await this.countBlockedPayments(),
          chargebackRate: await this.calculateChargebackRate(),
          riskScoreDistribution: await this.getRiskScoreDistribution(),
        };
      }
    }`}

  
**Співчення в реальному часі:**

    // lib/monitoring/payment-alerts.ts

{`export class PaymentMonitoringAlerts {
      async checkPaymentHealth() {
        const metrics = await this.analytics.getRevenueMetrics('24h');

        // Співщення про незвичні патерни
        if (metrics.conversionRate < 0.5) { // Нижче 50%
          await this.alert('Low conversion rate', metrics);
        }

        if (metrics.refundRate > 0.05) { // Вище 5%
          await this.alert('High refund rate', metrics);
        }

        // Перевірити статус шлюзу
        await this.checkGatewayConnectivity();
      }
    }`}

---

## Історії успіху

> **Success**
> **Результати інтеграції платежів:**

### Українська аграрна платформа
- **Інтеграція WayForPay** з локальними методами оплати
- **45% збільшення** успішних транзакцій
- **Підтримка мультивалютності** для експортних ринків
- **Модель підписки** з місячним доходом $12K

### Глобальний ринок фрілансерів
- **Інтеграція Stripe** з 135+ валютами
- **32% покращення** міжнародної конверсії
- **Відповідність 3D Secure** зменшення чарджбеків на 60%
- **Місячний обсяг** $250K+

### Платформа медичних послуг
- **Токенні платежі** для бронювання послуг
- **Інтеграція страхування** для медичного білінгу
- **Автоматизація відповідності** регуляторним вимогам охорони здоров'я
- **$2M річного доходу** з 15% take rate

---

## Наступні кроки

> **Success**
> **Готові інтегрувати платежі у вашу платформу Ring?**

### Фаза налаштування
- [ ] Виберіть платіжний шлюз(и) для вашого ринку
- [ ] Завершіть налаштування рахунку мерчанта та верифікацію
- [ ] Налаштуйте вебхуки та облікові дані API

### Фаза інтеграції
- [ ] Реалізуйте класи сервісів платежів
- [ ] Побудуйте форми checkout та платежів
- [ ] Налаштуйте управління підписками

### Тестування та запуск
- [ ] Ретельно протестуйте всі потоки платежів
- [ ] Налаштуйте моніторинг та аналітику
- [ ] Запустіть з заходами запобігання шахрайству

### Оптимізація
- [ ] Моніторте коефіцієнти конверсії та користувацький досвід
- [ ] A/B тестування потоків платежів
- [ ] Оптимізуйте для мобільних методів оплати

> **Info**
> **Потрібна допомога з інтеграцією платежів?** Опублікуйте [можливість налаштування Ring](/opportunities?type=ring_customization) для експертів з платежів, знайомих з вашими цільовими ринками та вимогами відповідності.
