Інтеграція платіжного шлюзу Stripe в мобільний додаток

TRUETECH займається розробкою, підтримкою та обслуговуванням мобільних додатків iOS, Android, PWA. Маємо великий досвід та експертизу для публікації мобільних додатків до популярних маркетів Google Play, App Store, Amazon, AppGallery та інші.

Розробка та підтримка будь-яких видів мобільних додатків:

Інформаційні та розважальні мобільні програми
Новинки, ігри, довідники, онлайн-каталоги, погодні, фітнес та здоров'я, туристичні, освітні, соціальні мережі та месенджери, квіз, блоги та подкасти, форуми, агрегатори
Мобільні програми електронної комерції
Інтернет-магазини, B2B-додатки, маркетплейси, онлайн-обмінники, кешбек-сервіси, біржі, дропшиппінг-платформи, програми лояльності, доставка їжі та товарів, платіжні системи
Мобільні програми для управління бізнес-процесами
CRM-системи, ERP-системи, управління проектами, інструменти для команди продажів, облік фінансів, управління виробництвом, логістика та доставка, управління персоналом, системи моніторингу даних
Мобільні програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, платформи надання електронних послуг, платформи кешбеку, відеохостинги, тематичні портали, платформи онлайн-бронювання та запису, платформи онлайн-торгівлі

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

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1735 послуг
Інтеграція платіжного шлюзу Stripe в мобільний додаток
Складний
~3-5 днів
Часті запитання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_mobile-applications_feedme_467_0.webp
    Розробка мобільного додатка для компанії FEEDME
    792
  • image_mobile-applications_xoomer_471_0.webp
    Розробка мобільного додатку для компанії XOOMER
    671
  • image_mobile-applications_rhl_428_0.webp
    Розробка мобільного додатку для компанії RHL
    1097
  • image_mobile-applications_zippy_411_0.webp
    Розробка мобільного додатку для компанії ZIPPY
    969
  • image_mobile-applications_affhome_429_0.webp
    Розробка мобільного додатку для компанії Affhome
    914
  • image_mobile-applications_flavors_409_0.webp
    Розробка мобільного додатку для компанії FLAVORS
    495

Інтеграція платіжного шлюзу Stripe в мобільному додатку

Stripe — технічно найбільш зрілий платіжний шлюз з точки зору мобільного SDK. SDK для iOS та Android охоплюють не лише базовий card input, а й Apple Pay, Google Pay, 3DS2, Link, а також збереження способів оплати через SetupIntent. Вибір правильного потоку залежить від завдання: одноразовий платіж, підписка, збереження карти без негайного списання — це різні API.

PaymentIntent проти SetupIntent: що використовувати

PaymentIntent — для негайного списання. Створюється на сервері, передається клієнту через client_secret, клієнт підтверджує.

SetupIntent — для збереження карти без списання (наприклад, при реєстрації, щоб потім списувати через API). Аналогічний потік, але без суми.

Основна помилка — створювання PaymentIntent на клієнті. secret_key ніколи не повинна потрапляти в додаток. Лише publishable_key — клієнтський.

iOS: PaymentSheet та користувацький потік

Stripe пропонує два підходи: готовий PaymentSheet (нативний UI від Stripe) та поелементний STPPaymentHandler.

PaymentSheet (рекомендується для старту)

import StripePaymentSheet

var paymentSheet: PaymentSheet?

func preparePaymentSheet(clientSecret: String, customerId: String, ephemeralKeySecret: String) {
    var config = PaymentSheet.Configuration()
    config.merchantDisplayName = "Your Company"
    config.customer = .init(id: customerId, ephemeralKeySecret: ephemeralKeySecret)
    config.applePay = .init(
        merchantId: "merchant.com.yourcompany.app",
        merchantCountryCode: "US"
    )
    config.defaultBillingDetails.address.country = "RU"
    config.allowsDelayedPaymentMethods = true

    paymentSheet = PaymentSheet(
        paymentIntentClientSecret: clientSecret,
        configuration: config
    )
}

@IBAction func checkoutTapped(_ sender: UIButton) {
    paymentSheet?.present(from: self) { [weak self] result in
        switch result {
        case .completed:
            self?.handleSuccess()
        case .failed(let error):
            print("Payment failed: \(error.localizedDescription)")
        case .canceled:
            break
        }
    }
}

Користувацький потік з CardField

Якщо потрібен повний контроль над UI:

let cardField = STPPaymentCardTextField()

// Підтвердження платежу
STPPaymentHandler.shared().confirmPayment(
    paymentParams,
    with: self
) { [weak self] status, paymentIntent, error in
    switch status {
    case .succeeded:
        self?.handleSuccess()
    case .failed:
        print("Error: \(error?.localizedDescription ?? "")")
    case .canceled:
        break
    @unknown default:
        break
    }
}

Android: PaymentSheet та CardInputWidget

import com.stripe.android.paymentsheet.PaymentSheet
import com.stripe.android.paymentsheet.PaymentSheetResult

private lateinit var paymentSheet: PaymentSheet

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    paymentSheet = PaymentSheet(this) { result ->
        when (result) {
            is PaymentSheetResult.Completed -> handleSuccess()
            is PaymentSheetResult.Failed -> {
                Log.e("Stripe", result.error.message ?: "Unknown error")
            }
            is PaymentSheetResult.Canceled -> {}
        }
    }
}

fun launchPaymentSheet(clientSecret: String, customerId: String, ephemeralKey: String) {
    val config = PaymentSheet.Configuration(
        merchantDisplayName = "Your Company",
        customer = PaymentSheet.CustomerConfiguration(customerId, ephemeralKey),
        googlePay = PaymentSheet.GooglePayConfiguration(
            environment = PaymentSheet.GooglePayConfiguration.Environment.Production,
            countryCode = "RU",
            currencyCode = "RUB"
        ),
        allowsDelayedPaymentMethods = true
    )

    paymentSheet.presentWithPaymentIntent(clientSecret, config)
}

3DS2: що відбувається під капотом

Stripe SDK обробляє 3DS2 автоматично в рамках confirmPayment / PaymentSheet.present. Коли банк вимагає підтвердження, SDK відкриває нативне 3DS2 завдання (біометрія або OTP) прямо в додатку — без перенаправлення браузера. Це важливо: перенаправлення 3DS1 через WebView часто втрачає callback, і транзакція зависає.

Якщо ваш постачальник повертає requires_action у статусі PaymentIntent — це нормально, Stripe SDK сам обробить завдання.

Типові проблеми

No such PaymentIntent — клієнт використовує client_secret з іншого середовища (test key з live secret або навпаки). Publishable key і client_secret повинні бути з одного середовища.

PaymentSheet не відкривається на Android, немає помилки. Stripe PaymentSheet вимагає FragmentActivity, а не простої Activity. Якщо запускаєте звичайної Activity — отримуєте тихий відмову.

Ephemeral key видалений. Stripe Ephemeral Keys живуть 1 годину. Якщо користувач довго сидить на екрані оплати — ключ протухає, PaymentSheet падає при спробі завантажити збережені способи оплати. Потрібно оновлювати ключ перед відкриттям sheet.

Серверна частина (мінімальний бекенд)

# FastAPI / Django / Laravel — логіка однакова
stripe.api_key = settings.STRIPE_SECRET_KEY

@app.post("/create-payment-intent")
async def create_payment_intent(amount: int, currency: str = "rub"):
    intent = stripe.PaymentIntent.create(
        amount=amount,  # у копійках
        currency=currency,
        automatic_payment_methods={"enabled": True},
    )
    return {"clientSecret": intent.client_secret}

Обсяг робіт

  • Реалізація PaymentSheet або користувацького card flow на iOS та Android
  • Серверний endpoint для створення PaymentIntent / SetupIntent
  • Інтеграція Apple Pay та Google Pay через Stripe
  • Налаштування Webhooks для остаточного підтвердження статусу платежу
  • Тестування з тестовими картами Stripe (4242 4242 4242 4242 та сценарії 3DS)

Терміни

3–5 днів для повної інтеграції з Apple Pay, Google Pay та 3DS2. Лише базовий card flow — 1–2 дні. Вартість розраховується індивідуально.