Авторизация по номеру телефона на python
Недавно появилась задача добавить на один из своих сервисов авторизацию по номеру телефона. Пришлось знатно порыться в интернетах и потратить немного времени на написание кода.
Для отправки смс я выбрал сервис sms.ru, у них самая низкая стоимость отправки сообщений примерно 1,7 рубля (из того что я нашел) и самое простое API + есть партнерская программа.

Регистрируемся на сервере и получаем в личном кабинете:

Теперь делаем небольшой скрипт для отправки и обработки запросов:
import dataclasses
import requests
import logging
import re
log = logging.getLogger("SMS")
@dataclasses.dataclass()
class TSMSResponse:
    id: str = "0"
    status: int = 0
    status_code: int = -1
    balance: float = 0
class SMSTransport:
    _URL = "https://sms.ru/sms/send"
    def __init__(self, api_id):
        self._api_id = api_id
    def send(self, to: str, msg: str) -> TSMSResponse:
        if not self.validate_phone(to):
            log.error("Invalid phone number")
            return TSMSResponse()
        response = requests.get(self._URL, params=dict(
            api_id=self._api_id,
            to=to,
            msg=msg,
            json=1
        )).json()
        log.debug("Response %s", response)
        if response["status"] == "OK":
            phone = response["sms"][to]
            if phone["status"] == "OK":
                return TSMSResponse(
                    status=1,
                    status_code=phone["status_code"],
                    balance=response['balance'],
                    id=phone["sms_id"]
                )
        log.debug("Error status %s", response)
        return TSMSResponse(
            status_code=response["status_code"]
        )
    @classmethod
    def validate_phone(cls, phone):
        return re.match(r"^7[0-9]{10}$", phone)В примере используется dataclass, данный модуль появился только в Python3.8
Как выидно из примера, это класс для отправки телефона, метод send, принемает два параметра:
- to - номер получателя в формате 79999999999
- msg - текст сообщения в кодировке UTF-8
Не смотря на то что api сервиса умеет принимать больше одного номера за раз или пачку сообщений, данная реализация отправляет 1 сообщение на 1 номер за раз, так как задача авторизация а не спам рассылка.
В ответ send возвращает объект SMSResponse со статусом ответа 1/0 и кодом ответа где:
- 100 - Запрос выполнен или сообщение находится в очереди на отправку
- 103 - Сообщение доставлено
- 200 - Неправильный api_id
- 201 - Не хватает средств на лицевом счету
- 202 - Неправильно указан номер телефона получателя, либо на него нет маршрута
- 203 - Нет текста сообщения
- 205 - Сообщение слишком длинное (превышает 8 СМС)
Эти и другие коды ответов можно найти на странице документации.
И использование скрипта:
api_id = "you api id"
sms = SMSTransport(api_id)
result = sms.send("79999999999", "hello")
print(result)
# TSMSResponse(id='201945-1000004', status=1, status_code=100, balance=110)Модуль получился максимально простой и надеюсь кому-то пригодится.