なぜ実現したいのか。
- LINEを使ったユーザー登録を実装済み
- LINEを使った通知機能をユーザーに使ってもらいたい
- 今の実装だと、LINEを使ったユーザー登録にしかできず、LINEだけの紐づけが出来ずに既存のユーザーがLINEとの連携が出来ない
という状況を改善するために本記事を記載して、自分の実装内容についてまとめていく。
今回の記事の内容について
まずは、LINEを使ったユーザー登録の記載とMessingAPIの導入についての流れを記載してから、その後LINEとの連携だけを実装する内容を記事にします。
技術構成
カテゴリ | 技術内容 |
---|---|
サーバーサイド | Ruby 3.2.3 |
フレームワーク | Rails 7.2.1 |
フロントエンド | HTML, CSS, Bootstrap, Hotwire(JS) |
開発環境 | Docker |
事前処理
LINEを使ったユーザー登録
sorceryを使ったサブモジュールでの登録
今回はsorceryを使った認証機能のため、sorceryのサブモジュールを使っての認証機能を作成しています。
https://github.com/Sorcery/sorcery/wiki/External
sorceryのGEMを参考に実装していく。以下に実装の内容をまとめる。
- LINEログインAPIの取得
- sorceryのサブモジュールのインストール
- 外部認証用のテーブルの作成(authenticationsテーブル)
- モデルファイルで関係性の定義
-
config/initializers/sorcery.rb
で受け取るLINEの設定 -
/oauths_controller.rb
の作成をしてログインについての処理の記載 - ルーティングの記載
- ビューファイルで配置
- ngrokの導入でテスト環境をHTTPS通信に切り替えて実装
MessingAPIの導入
実装済みについて
- 既に実装済みのnotificationsテーブルを生かして実装。
- アプリケーション内では通知は受け取る前提に。
- LINEの通知のONとOFFだけを切り替えられるように、usersテーブルにline_notification_enabledを作成する
以下に実装順序と実装をしたこと
- LINEのMessingAPIの導入
- ユーザーテーブルに
line_notification_enabled
の作成 -
line-bot-api
GEMの導入 - NotificationsControllerを使って、LINEのメッセージが届くように実施
メインの実装(※ここから本題です)
問題の確認
冒頭で述べた通りですが改めて実装内容としては以下の通りです。
- 「LINEでの通知を実施したい場合、ユーザーにはLINEのユーザーIDを保存する必要がある」
- 「現状がLINEでのユーザー登録及びログインしか出来ず、ログイン済みのユーザーは紐づける方法がない」
という2点が実装中でおきた問題です。
-
「LINEでの通知を実施したい場合、ユーザーにはLINEのユーザーIDを保存する必要がある」
問題:sorceryでの認証として必要なことと、LINE固有のIDが紐づけできていないこと
理由:保存先がusersテーブルの、emailで受け取るようにしている
解決:LINEの固有のIDを受け取るためのカラムを追加してそれで保存すること
-
「現状がLINEでのユーザー登録及びログインしか出来ず、ログイン済みのユーザーは紐づける方法がない」
問題:sorceryでの認証ではLINEとの連携が出来ない
理由:Sorceryの外部認証は新規ユーザー作成を前提とした設計であること
解決:omniauth-lineを導入して、かつ、別のLINEのログインAPIも導入してコールバック先も分けて実装
という実装をしていきます。
LINEのユーザーIDを保存するように変更
-
users テーブルに line_user_id カラムを追加と、email カラムの null: false 制約を削除
-
config/initializers/sorcery.rb内のマッピングの内容を変更
email→line_user_idに変更# LINE認証に関すること config.line.key = ENV['LINE_Sorcery_ID'] config.line.secret = ENV['LINE_Sorcery_SECRET'] # 本番環境のURLに置き換える config.line.callback_url = '<https://smart-phone-choice.com/oauth/callback?provider=line>' #ユーザーを識別するためのOpenID Connect IDトークンとメールアドレス config.line.scope = "profile openid email" config.line.bot_prompt = 'aggressive' # 以下の内容にline_user_idを使う config.line.user_info_mapping = { name: 'displayName', line_user_id: 'userId' }
-
app/controllers/oauths_controller.rb 内に、skip_before_action :require_loginを追記する
omniauth-lineを導入して連携の処理のみの記載
-
Gemfile内にgem 'omniauth-line’の導入
gem 'omniauth-line' gem 'omniauth-rails_csrf_protection' # CSRF対策
-
config/initializers/omniauth.rbの作成と編集
Rails.application.config.middleware.use OmniAuth::Builder do # LINEのプロバイダーとスコープの指定 provider :line, ENV['LINE_OmniAuth_ID'], ENV['LINE_OmniAuth_SECRET'], scope: 'profile openid email', bot_prompt: 'aggressive', # 本番環境のコールバックURLに変更する callback_url: '<https://smart-phone-choice.com/auth/line/callback?provider=line>' # 認証後にリダイレクトされるURL end
-
config/routes.rb の追加
# 既存ユーザーのLINE連携用のLineConnectionsController用のルートを追加 get '/auth/line/callback', to: 'line_connections#callback' # LINE連携ページへのルート post '/auth/line/callback', to: 'line_connections#callback' # LINE連携処理を行うルート
-
app/controllers/line_connections_controller.rbでコールバックの記載
class LineConnectionsController < ApplicationController before_action :require_login def callback auth = request.env['omniauth.auth'] if current_user.update(line_user_id: auth.uid) redirect_to my_profile_path, success: t('defaults.flash_message.line_success') else redirect_to my_profile_path, danger: t('defaults.flash_message.line_failure') end end end
-
ビューファイルで条件先を埋め込む
<% if current_user.line_registered? %> <p>LINEでの登録済み</p> <% else %> <!-- LINEの後から連携のユーザー用 --> <% if current_user.omniauth_user_linked_to_line? %> <p>LINEとの連携済み</p> <% else %> <%= button_to 'LINEと連携する', '/auth/line', method: :post, data: { turbo: false }, class: 'btn btn-success' %> <% end %> <% end %>
MessingAPIとの連携。公式アカウントのリンク先の追加。
LINEログインAPI内の「チャンネル基本設定」の「友達追加オプション」にりんくされたLINEの公式アカウントとして追加する
念のため、公式アカウントのリンク先を追加(MessingAPIの友達かた結局通知が届くので)
<a href="<https://lin.ee/0NVtMsf>"><img src="<https://scdn.line-apps.com/n/line_add_friends/btn/ja.png>" alt="友だち追加" height="36" border="0"></a>
出来上がりのLINEのDevelopサイトと
SMC_testで、sorceryのサブモジュールで使うLINEを使ったユーザー登録
SMC連携でomniauth使う既存のユーザーのLINEとの連携
すまちょい公式でMessingAPIを使った通知
という風に分けています。
まとめ
初学者の私にとっては、ログの内容を見ながら、どういう処理の中でどのようにしてデータが保存されているのかと確認しながらの実装で、テーブル設計の部分についてでしたので非常に勉強になった実装です。
また、データベースに保存する実施をしましたが、Webhookやトークンを使うことで、データベースに保存せずにMessingAPIを主体に通知機能も出来るのでは?
と思ったので、今後実装出来ればと思っています。
あくまで、LINEでのユーザー登録やMessingAPIの導入済みの方が、既存ユーザーにどう連携したらいいのか?と思った際に参考をしていただけると幸いです。
ありがとうございました。