Подключение

Важно

Поддерживаемые версии:

  • iOS — 14.0 и выше.
  • Swift — 6.0 и выше.

Этот способ интеграции требует настройки API. Подробнее о способах интеграции см. в разделе Интеграция Яндекс Пэй и Сплит.

Шаг 1. Подготовка идентификаторов

Перед началом интеграции получите идентификаторы, которые понадобятся при подключении SDK:

  • Merchant ID — идентификатор магазина в личном кабинете Яндекс Пэй. Узнать Merchant ID
  • iOS Appid — точный App ID iOS-приложения, состоящий из Prefix и Bundle ID. Подробнее об App ID
  • Client ID (YANDEX_CLIENT_ID) — идентификатор приложения в сервисе Яндекс OAuth. Как получить Client ID, читайте ниже.

Получение Client ID

Чтобы получить Client ID, зарегистрируйте приложение в сервисе Яндекс OAuth — это нужно, чтобы покупатели при оплате через Яндекс Пэй могли авторизоваться с помощью своего Яндекс ID.

Важно

Аккаунт, с которого вы регистрируете приложение в Яндекс OAuth, должен в Яндекс ID состоять в организации и иметь права разработчика. Добавить аккаунт в организацию и выдать права может сотрудник с ролью Владелец или Администратор.

Как проверить наличие прав
  • Если аккаунт состоит организации, в Яндекс OAuth при нажатии на фото профиля отображается название организации:

  • Чтобы проверить наличие прав разработчика, в Яндекс ID перейдите в список сотрудников организации → профиль сотрудника → Права в сервисах → Яндекс ID для сайта:

  1. Перейдите в сервис Яндекс OAuth, нажмите кнопку Создать, выберите вариант Для авторизации пользователей и перейдите к созданию.

  2. В поле Название вашего сервиса укажите название, которое будет отображаться пользователям на экране авторизации, и загрузите иконку приложения.

  3. В разделе Платформы приложений выберите iOS-приложение и укажите его параметры:

    • iOS Appid — точный идентификатор iOS-приложения, например A1B2C3D4E5.com.domain.application, который состоит из Prefix и Bundle ID;
    • iOS AppStore URL — ссылка на приложение в AppStore.

    Примечание

    Подробнее про идентификаторы iOS-приложений читайте в документации Apple.

  4. Добавьте доступ к Яндекс Пэй: в разделе Права доступа к данным пользователей в поле Название доступа укажите и выберите Оплата через Yandex Pay.

    Примечание

    Доступ Управление заказами Yandex Pay Checkout не требуется. Если он у вас добавлен, удалите его.

  5. Нажмите кнопку ПродолжитьВсё верно, создать приложение и скопируйте значение поля Client ID.

  6. В разделе Настройки личного кабинета Яндекс Пэй нажмите Добавить Client ID и укажите значение Client ID.

    Там же в разделе Настройки нажмите Добавить приложения, выберите нужный Client ID, платформу приложения и укажите iOS Appid в поле appID для iOS.

Шаг 2. Настройка проекта

Подготовьте iOS-проект к работе с Яндекс Пэй SDK: добавьте полученный Client ID и настройте Universal Links для обмена данными с приложениями Яндекса.

2.1 Настройка Info.plist

Добавьте в файл Info.plist строки:

<key>YANDEX_CLIENT_ID</key>
<string>$(YANDEX_CLIENT_ID)</string>

Где YANDEX_CLIENT_ID — Client ID, полученный на предыдущем шаге.

2.2 Настройка Entitlements

Сервис авторизации обменивается информацией с приложениями Яндекса через Universal Links. Добавьте следующие строки в Capability: Associated Domains или файл *.entitlements:

<key>com.apple.developer.associated-domains</key>
<array>
  <string>applinks:$(YANDEX_CLIENT_ID).merchant.applink.pay.yandex.ru</string>
  <string>applinks:$(YANDEX_CLIENT_ID).merchant.applink.sandbox.pay.yandex.ru</string>
</array>
<key>com.apple.developer.associated-domains</key>
<array>
  <string>applinks:$(YANDEX_CLIENT_ID).merchant.applink.pay.yandex.ru</string>
</array>

Где YANDEX_CLIENT_ID — Client ID, полученный на предыдущем шаге.

Шаг 3. Установка Yandex Pay SDK

Важно

Текущая версия YandexPaySDK — 1.25.0.

Добавьте зависимость в Podfile:

pod 'YandexPaySDK/Static'
  1. В навигаторе проектов Project Navigator в окне Xcode выберите свой проект (если у вас используется Workspace).

  2. В верхнем меню нажмите File → Add Package Dependencies....

  3. Добавьте пакет по ссылке: https://github.com/yandexmobile/yandex-pay-ios

    Внимание

    Рекомендуем использовать статическую библиотеку YandexPaySDK. Она оптимизирована по размеру, и все зависимости подключаются независимо.

    Динамическая версия библиотеки требует, чтобы все зависимости были вкомпилированы в итоговый бинарный фреймворк. Из-за этого зависимости нельзя пеереиспользовать корректно.

Добавьте зависимость Swift Package в Package.swift:

let package = Package(
    ...
    dependencies: [
        .package(
            name: "YandexPaySDK",
            url: " https://github.com/yandexmobile/yandex-pay-ios"
        ),
    ],
    ...
)

Внимание

На текущий момент поддерживается только скомпилированная библиотека — как статичечcкая, так и динамическая. Статическая библиотека использует зависимости SPM, в то время как динамическая библиотека включает все необходимые зависимости.

Распространение исходным кодом недоступно из-за ограничений, связанных с PCI DSS.

Шаг 4. Инициализация Yandex Pay SDK

  1. Инициализируйте SDK в AppDelegate.swift вашего проекта в методе application(_:didFinishLaunchingWithOptions:):

    import YandexPaySDK
    
      func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Укажите конфигурацию
        let merchant = YandexPaySDKMerchant(
            // Merchant ID магазина из личного кабинета Яндекс Пэй
            id: "MERCHANT_ID",
            // Наименование продавца (магазина)
            name: "MERCHANT_NAME",
            // URL сайта продавца (магазина)
            url: "https://example.org/"
        )
        let configuration = YandexPaySDKConfiguration(
            // Необходимое окружение: .sandbox — для тестовой среды, .production — для боевой среды
            environment: .sandbox,
            // Информация о продавце
            merchant: merchant,
            // Локализация
            locale: .ru
        )
          // Инициализируйте SDK
        YandexPaySDKApi.initialize(configuration: configuration)
    
        // Инициализируйте UIWindow и ViewController
        let window = UIWindow(frame: UIScreen.main.bounds)
        window.rootViewController = PaymentURLViewController()
        window.makeKeyAndVisible()
        self.window = window
        return true
      }
    
    import YandexPaySDK
    
      func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let windowScene = scene as? UIWindowScene else {
          return
        }
    
        // Укажите конфигурацию
        let merchant = YandexPaySDKMerchant(
            // Merchant ID магазина из личного кабинета Яндекс Пэй
            id: "MERCHANT_ID",
            // Наименование продавца (магазина)
            name: "MERCHANT_NAME",
            // URL сайта продавца (магазина)
            url: "https://example.org/"
        )
        let configuration = YandexPaySDKConfiguration(
            // Необходимое окружение: .sandbox — для тестовой среды, .production — для боевой среды
            environment: .sandbox,
            // Информация о продавце
            merchant: merchant,
            // Локализация
            locale: .ru
        )
        // Инициализируйте SDK
        YandexPaySDKApi.initialize(configuration: configuration)
    
        // Инициализируйте UIWindow и ViewController
        let window = UIWindow(windowScene: windowScene)
        window.rootViewController = PaymentURLViewController()
        window.makeKeyAndVisible()
        self.window = window
      }
    

    Укажите вручную параметры конфигурации SDK:

    • merchant — данные продавца:

      • idMerchant ID магазина из личного кабинета Яндекс Пэй;
      • name — наименование продавца (магазина);
      • url — URL сайта продавца (магазина).
    • configuration:

      • environment — среда выполнения Yandex Pay SDK: .sandbox или .production;
      • locale — язык интерфейса (например, .ru для русского).
  2. В AppDelegate.swift вашего проекта добавьте нотификацию YandexPaySDK о событиях жизненного цикла приложения:

    import YandexPaySDK
    
      func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
          // Проверьте, что SDK проинициализирован
          guard YandexPaySDKApi.isInitialized else {
            assertionFailure("YandexPaySDK is not initialized.")
            return false
          }
    
          return YandexPaySDKApi.instance.applicationDidReceiveUserActivity(userActivity)
      }
    
      func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
          // Проверьте, что SDK проинициализирован
          guard YandexPaySDKApi.isInitialized else {
            assertionFailure("YandexPaySDK is not initialized.")
            return false
          }
    
          return YandexPaySDKApi.instance.applicationDidReceiveOpen(url, options: options)
      }
    
    import YandexPaySDK
    
      func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
        // Проверьте, что SDK проинициализирован
        guard YandexPaySDKApi.isInitialized else {
          assertionFailure("YandexPaySDK is not initialized.")
          return false
        }
    
        YandexPaySDKApi.instance.applicationDidReceiveUserActivity(userActivity)
      }
    
      func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
        // Проверьте, что SDK проинициализирован
        guard YandexPaySDKApi.isInitialized else {
          assertionFailure("YandexPaySDK is not initialized.")
          return false
        }
    
        guard
          let context = URLContexts.first
        else { return }
    
        YandexPaySDKApi.instance.applicationDidReceiveOpen(
          context.url,
          options: [.sourceApplication: context.options.sourceApplication as Any]
        )
      }
    

Примеры использования

Для ознакомления доступен демо-проект. В нем есть пример настройки проекта, а также два вида интеграции:

  • кнопка Яндекс Пэй с вызовом формы оплаты при ее нажатии;
  • программный вызов формы оплаты из кода.

Добавление кнопки Яндекс Пэй с созданием заказа по ссылке на экран в Swift-проекте

Если вы хотите создать кнопку с новым методом создания заказа, используйте сигнатуру createButton(dataSource:delegate:) класса YandexPaySDKApi.

Пример использования кнопки во ViewController:

import YandexPaySDK

  final class PaymentURLViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        view.backgroundColor = .systemBackground

        // Проверьте, что SDK проинициализирован
        guard YandexPaySDKApi.isInitialized else {
          assertionFailure("YandexPaySDK is not initialized.")
          return
        }

        // Настройте отображение кнопки
        let buttonModel = YPButtonModel(
            amount: 1000,
            currency: .rub,
            preferredPaymentMethods: [.card, .split],
            appearance: .system,
            cornerRadius: 16,
            isLoading: false,
            isBordered: false
        )

        // Создайте кнопку
        let button: UIView = YandexPaySDKApi.instance.createButton(
            model: buttonModel,
            paymentDataProvider: self,
            presentationContextProvider: self,
            delegate: self
        )

        // Добавьте кнопку в иерархию
        view.addSubview(button)

        // Установите layout для кнопки
        button.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            button.centerXAnchor.constraint(equalTo: view.  centerXAnchor),
            button.centerYAnchor.constraint(equalTo: view.  centerYAnchor),
            button.widthAnchor.constraint(equalToConstant: 250)
        ])
    }
}

Кнопка для взаимодействия с клиентским приложением использует делегат YandexPayButtonDelegate. Реализуйте этот делегат, чтобы передать его кнопке при ее создании:

extension PaymentURLViewController: YandexPayButtonDelegate {
    func yandexPayButton(
        _ button: YandexPayButtonProtocol,
        didCompletePaymentWithResult result: YPYandexPayPaymentResult,
        data: YandexPaySDK.YPYandexPayPaymentData
    ) {
        let title: String
        let message: String
        switch result {
        case .succeeded:
            title = "Success!"
            message = "Payment successfuly proceeded."
        case .cancelled:
            title = "Cancelled!"
            message = "Payment has been cancelled by user."
        case .failed:
            fallthrough
        @unknown default:
            title = "Error!"
            message = "An error occured while payment processing."
        }

        let controller = UIAlertController(title: title, message: message, preferredStyle: .alert)
        controller.addAction(UIAlertAction(title: "OK", style: .default))
        present(controller, animated: true)
    }
}

В этом примере мы показываем пользователю сообщение с текущим статусом оплаты через YandexPay.

Кнопка использует протоколы datasource YPButtonPaymentDataProviding и YPButtonPresentationContextProviding. Реализуйте указанные протоколы, чтобы передать их кнопке при ее создании:

// MARK: - YPButtonPaymentDataProviding

extension PaymentURLViewController: YPButtonPaymentDataProviding {
  func paymentUrl(for yandexPayButton: YandexPayButtonProtocol) async throws -> String {
    // Запросите paymentUrl (создайте заказ) асинхронно с вашего бэкенда
    await withCheckedContinuation { continuation in
      // Это пример реализации async кода, скорее всего, здесь будет сетевой запрос
      DispatchQueue.main.async {
        continuation.resume(returning: "payment-url.ru")
      }
    }
  }
}

// MARK: - YPButtonPresentationContextProviding

extension PaymentURLViewController: YPButtonPresentationContextProviding {
  func anchorForPresentation(for yandexPayButton: any YandexPayButtonProtocol) -> YPPresentationContext {
    // Предоставьте UIViewController, с которого необходимо показать форму YandexPay по нажатию на кнопку
    .viewController(self)
  }
}

Все методы запроса данных являются асинхронными. Это значит, что они должны работать с подходом Swift Concurrency. Если есть необходимость, можно вернуть значение сразу.

Примечание

Смотрите также пример от Apple с WWDC 2021, как перевести элементы вашего кода c подхода GCD на подход Concurrency: Swift concurrency: Update a sample app.

Предыдущая