Отправка SMS на Swift (iOS/macOS): API MessageUI и сторонние сервисы

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Отправка SMS на Swift (iOS/macOS): API и библиотеки

В разработке под iOS и macOS часто возникает необходимость отправлять SMS-сообщения — для верификации пользователей, отправки уведомлений или интеграции с CRM. В этой статье мы рассмотрим два основных подхода: использование встроенного фреймворка MessageUI для отправки SMS через системное приложение и интеграцию с облачными SMS-провайдерами (Twilio, Nexmo/Vonage) через HTTP API. Также обсудим ограничения и лучшие практики.

1. Отправка SMS через MessageUI (только iOS)

Фреймворк MessageUI предоставляет контроллер MFMessageComposeViewController, который позволяет отправить SMS из вашего приложения, используя стандартный интерфейс iOS. Важно: этот метод работает только на реальных устройствах (не в симуляторе) и требует активной SIM-карты.

Шаг 1: Подключение фреймворка

Добавьте импорт в файл, где будете работать с SMS:

import MessageUI

Шаг 2: Проверка возможности отправки

Перед вызовом контроллера обязательно проверьте, может ли устройство отправлять SMS:

if MFMessageComposeViewController.canSendText() {
    // можно отправлять
} else {
    // показать ошибку пользователю
}

Шаг 3: Создание и настройка контроллера

let messageVC = MFMessageComposeViewController()
messageVC.body = "Ваш код подтверждения: 123456"
messageVC.recipients = ["+79001234567"]
messageVC.messageComposeDelegate = self // не забудьте установить делегат
present(messageVC, animated: true, completion: nil)

Шаг 4: Реализация делегата

extension YourViewController: MFMessageComposeViewControllerDelegate {
    func messageComposeViewController(_ controller: MFMessageComposeViewController, didFinishWith result: MessageComposeResult) {
        controller.dismiss(animated: true) {
            switch result {
            case .sent:
                print("SMS отправлено")
            case .cancelled:
                print("Отменено")
            case .failed:
                print("Ошибка отправки")
            @unknown default:
                break
            }
        }
    }
}

Ограничения:

  • Не работает в симуляторе.
  • Пользователь видит интерфейс и может изменить сообщение.
  • Не подходит для автоматической отправки (например, серверной части).
  • Недоступно на macOS (только iOS).

2. Отправка SMS через сторонние API (Twilio, Nexmo и др.)

Для серверной отправки SMS (без участия пользователя) используйте HTTP API облачных провайдеров. Рассмотрим пример с Twilio — одним из самых популярных сервисов.

Шаг 1: Получение учетных данных

Зарегистрируйтесь в Twilio, получите Account SID, Auth Token и номер телефона отправителя (например, +15005550006 для тестов).

Шаг 2: Отправка POST-запроса

Используйте URLSession для вызова API Twilio:

func sendSMSviaTwilio(to recipient: String, message: String) {
    let accountSID = "YOUR_ACCOUNT_SID"
    let authToken = "YOUR_AUTH_TOKEN"
    let fromNumber = "+15005550006"
    
    let urlString = "https://api.twilio.com/2010-04-01/Accounts/\(accountSID)/Messages.json"
    guard let url = URL(string: urlString) else { return }
    
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    let loginString = "\(accountSID):\(authToken)"
    let loginData = loginString.data(using: .utf8)!
    let base64LoginString = loginData.base64EncodedString()
    request.setValue("Basic \(base64LoginString)", forHTTPHeaderField: "Authorization")
    
    let bodyParams = [
        "From": fromNumber,
        "To": recipient,
        "Body": message
    ]
    let bodyString = bodyParams.map { "\($0.key)=\($0.value)" }.joined(separator: "&")
    request.httpBody = bodyString.data(using: .utf8)
    
    URLSession.shared.dataTask(with: request) { data, response, error in
        guard let data = data, error == nil else {
            print("Ошибка запроса: \(error?.localizedDescription ?? "неизвестная")")
            return
        }
        if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 201 {
            print("SMS успешно отправлено через Twilio")
        } else {
            print("Ошибка сервера: \(String(data: data, encoding: .utf8) ?? "")")
        }
    }.resume()
}

Альтернативы: Nexmo (Vonage) и другие

API других провайдеров работают аналогично — POST-запрос с базовой

Рекомендаций