Как-то раз передо мной стояла задача сделать подтверждение номера телефона. И, так как у меня совсем нет звездочек на гитхабе (и инвайта на хабре), было принято решение сделать гем.

image

В качестве смс-шлюза был выбран сервис Twilio, ибо он удобный и недорогой. Потратив на это дело несколько часов, получился, как по мне, весьма удобный гем.

Чтобы установить его, надо добавить в гемфайл:

gem "twilio_phone_verification"

После чего выполнить команду:

bundle install

И

rails g twilio_phone_verification:install [USER_CLASS]

USER_CLASS это класс, для которого надо добавить проверку телефона. Note:надо, чтобы у данного класса было поле name, чтобы он смог отправит смску «Hello, {{name}} ...». Это создаст 2 файла:

config/initializers/twilio_phone_verification.rb конфиг файл, где надо ввести ключи и номер телефона из Twilio

TwilioPhoneVerification.configure do |config|
  config.account_sid = ENV.fetch("TWILIO_ACCOUNT_SID") # Paste account id here
  config.auth_token = ENV.fetch("TWILIO_AUTH_TOKEN") # Paste your twilio auth token here
  config.from = ENV.fetch("TWILIO_NUMBER") # Paste your twilio number here
end

и db/migrate/000000000000000_add_phone_to_users.rb миграция, которая создаст нужные поля:

class AddPhoneToUsers < ActiveRecord::Migration[5.0]
  def self.up
    add_column :users, :phone, :string
    add_column :users, :phone_confirmation_token, :string
    add_column :users, :phone_confirmed_at, :datetime
    add_column :users, :phone_confirmation_sent_at, :datetime
    add_index :users, :phone, unique: true
  end

  def self.down
    remove_column :users, :phone
    remove_column :users, :phone_confirmation_token
    remove_column :users, :phone_confirmed_at
    remove_column :users, :phone_confirmation_sent_at
  end
end

После чего выполнить команду:

rails db:migrate # rails 5
rake db:migrate # rails < 5

И добавить в модель консерн, чтобы добавились нужные методы:

class User < ActiveRecord::Base
  include TwilioPhoneVerification::Phonable
end

Это добавит 4 основных метода: phone_confirmed? возвращает true или false, в зависимости от того, подтвержден ли телефон.

send_phone_confirmation генерирует код и отправляет смску. Возвращает {success: true}, если смска отправилась, или false, если не отправилась. Каждый раз генерируется новая смска. И код может быть отправлен только 1 раз в минуту.

confirm_phone_by_code(code) возвращает true и верифицирует номер телефона, если код верный, иначе false.

confirm_phone верифицирует номер телефона без проверки кода.

Если метод возвращает false, то ошибка добавляется в .errors.

Также есть 2 таймстампа:

phone_confirmed_at когда был подтвержден телефон
phone_confirmation_sent_at когда была отправлена последняя смска

» Github repo

На этом все. Спасибо за внимание.
Поделиться с друзьями
-->

Комментарии (11)


  1. mihmig
    02.11.2016 16:40

    53 копейки за СМС с «левого номера»?


  1. MrVebber
    02.11.2016 21:38

    Только один вопрос — зачем вам делать подтверждение номеров телефонов?
    Раньше все сайты почту требовали — в итоге у меня сейчас на ящик, который я везде для регистрации использовал, в среднем за день приходит около 20 писем с рекламой и другим мусором.
    Сейчас уже номер требуют — на номер, который я использую исключительно для сайтов, пока приходит 3-4 смс с рекламой в неделю. и это при том, что зарегистрировался я только на десятке сайтов, где номер указал. Но ведь теперь уже даже самый захудалый сайт номер требует. Зачем? Что дальше?


    1. kaikash
      02.11.2016 21:47

      Иногда это необходимо иметь номер телефона пользователя. Например для интернет магазина, такси, доставка еды и пр…


    1. Kane
      09.11.2016 00:14

      А иногда это самый простой способ аутентифицировать пользователя, когда этого требует закон.


      1. MrVebber
        09.11.2016 00:23

        Хм… Когда это подобное закон требовал? Не слышал о таком. Можно подробнее?

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


        1. Kane
          09.11.2016 11:02

          Закон требует аутентификации пользователя при предоставлении услуг связи, например, при использовании публичного WiFi. Есть и другие случаи.


  1. stiverb
    03.11.2016 11:11

    Проверьте зависимости Вашего гема. В twilio_phone_verification.gemspec указано только:

    spec.add_dependency "twilio-ruby"
    spec.add_dependency "phony_rails"
    


    В коде используете гемы: railties, activesupport, activerecord — 5 версии.


    1. kaikash
      03.11.2016 11:11

      Да, верно, спасибо большое.


  1. am-amotion-city
    03.11.2016 22:43

    1, А зачем вы зависимости в Gemfile, а не в gemspec пишете? Это же гем, все-таки.


    1. В конфигураторе:
      def self.configure(&block) # зачем тут block, кроме как позлить линтер? :)
      yield configuration # а вот тут хорошо бы проверить: if block_given?
      # зачем тут вообще блок? чем def self.configure(acc_id, token, from) хуже?
      # блоки обычно же создаются, чтобы их можно было сколько угодно раз вызывать, где захотел подвинтить
      raise "Configuration error" unless configuration.account_sid && configuration.auth_token && configuration.from
      # кто такой configuration.from, что мы целый эксепшн бросим, если его нет, но нигде не используем?
      Twilio.configure do |config|
        config.account_sid = configuration.account_sid
        config.auth_token = configuration.auth_token
      end
      end
    2. Очень бы хотелось, чтобы провайдер был подключаемым, чтобы можно было своего провайдера подсунуть.
    3. Без CI (https://travis-ci.org/ или семафор, или еще что) проекты нынче выглядят немножечко не того :)

    А вообще здорово, что выкладывать код гемами на гитхаб входит в моду и у нас.


    1. kaikash
      03.11.2016 22:57

      А зачем вы зависимости в Gemfile, а не в gemspec пишете? Это же гем, все-таки.

      Первый гем комом :(

      1. Делалось немножко на коленке + я не очень опытный
        Насчет configuration.from — номер телефона, откуда отправляются смски, используется в twilio_service.rb
      2. Изначально хотел так сделать, но в итоге остановился на твилио и сделал только под него. Добавить другой провайдер не составит большого труда.
      3. Надеюсь, что я начну делать тесты :)


      Спасибо за советы и объективную критику!


  1. am-amotion-city
    09.11.2016 09:24

    Я просто положу это тут: https://twitter.com/outstarwalker/status/794828686633660416