はじめに
プログラミングスクール「RUNTEQ」を卒業し、
未経験にてエンジニア転職を目標に活動しています。
未経験であり、内容が間違っている可能性があります。気になる点がありましたら連絡ください。
また、記事で紹介しているやり方は私自身で考えた方法であるため、他に良いやり方があると思いますので、あくまで参考までにいただけたらと思います。
今回、個人開発ポートフォリオとして「ぶさかわフォト」を開発しました。
ぶさかわフォトについては下記記事を見て頂けたらうれしいです!
https://busakawa.com
ぶさかわフォトではユーザーをフォローし、フォローしたユーザーが投稿したときにLINE通知が来るように設定しました。
開発の中で、公式LINEを友達追加したときにLINEIDをDBへ保存する方法に苦戦したため、記事を書きたいと思います。
使用技術
カテゴリ | 技術 |
---|---|
フレームワーク | Rails7.1.3 |
バックエンド | Ruby3.2.3 |
DB
・Usersテーブルの"line_user_id"カラムに保存する
・LineBotTokensテーブルには"line_user_id"と"line_user_id_token"のカラムを準備し、一時的に保存する
前提として
1.sorceryにてアカウント作成後、ログインしている状態である。
※LINEにてログインしている場合は、sorceryの設定にてDB上にLINEIDを保存することは容易である。今回はsorceryでアカウントを作成後、公式LINEを友だち追加し、LINEIDをDBに保存する方法です。
手順
1.公式LINEのアカウント登録ボタンを作成
2.公式LINEを追加することで発生するwebhookイベントオブジェクトの処理
3.webhookイベント後の処理
1.公式LINEのアカウント登録ボタンを作成
先にコードを貼り付けます。
<%= link_to "https://lin.ee/ldrvLk4" do %>
<img src="https://scdn.line-apps.com/n/line_add_friends/btn/ja.png" alt="友だち追加" height="36" border="0">
<% end %>
リンクにつきましては、LINE Official Accountの友達追加ガイドを参照してください。
リンクを開くとこのようになり、
[]
公式LINEを表示できます。
(今回はテストの為友だちに登録済みです。となっています)
(2).公式LINEを追加することで発生するwebhookイベントオブジェクトの処理
ここからが今回の記事のキーポイントとなります。
前知識
・そもそもwebhookイベントとは?となると思いますので、下記URLを共有いたします。
https://developers.line.biz/ja/docs/messaging-api/receiving-messages/
一言で言えば、LINE公式アカウントを友だち追加したときに発生するHTTP POSTリクエストということです。
・webhookイベントオブジェクトはJSON形式で送られてきます。
https://developers.line.biz/ja/docs/messaging-api/receiving-messages/#webhook-event-in-one-on-one-talk-or-group-chat
では、説明してきます。
先にコードを共有いたします。
def webhook
body = request.body.read
events = client.parse_events_from(body)
events.each do |event|
case event
when Line::Bot::Event::Follow
user_id = event['source']['userId']
token = SecureRandom.alphanumeric(15)
LineBotToken.create(line_user_id: user_id, line_user_id_token: token)
message = [
{type: "text", text: "下記URLよりLINE認証を行ってください"},
{type: "text", text: "https://busakawa.com/line_bots/new?state=#{token}&openExternalBrowser=1"}
]
client.push_message(user_id,message)
end
end
webhookイベントが発生すると、ルーティングにて、webhookアクションを発生させるようにしています。(routes設定は省略いたします)
webhookイベントでは、
1.Followイベントの場合、userIDを取得し、変数へ。
2.SecureRandomnにて安全なランダム値を作成。
SecureRandomnについての詳細は下記参照
https://docs.ruby-lang.org/ja/latest/class/SecureRandom.html
3.messageの設定を行い公式LINE追加時にトークを送信する。
といった流れになっています。
・&openExternalBrowser=1を付けることで、LINEトークでのURLをブラウザで開くようにしています。 PC(Windows)の場合不要ですが、スマホ(IPhone)の場合はLINE内でURLを開いてしまいます。(Macbook Androidは分かりません)
なぜこのような処理にしたか
実施したこと
- webhookアクションにてcurrent_userを使う
最初はcurrent_userを使いました。
ログインしている状態で、公式LINEを追加することでUsersテーブルのline_user_idに保存するようにしましたが、ログにてcurrent_userが引っかかりエラーとなりました。
2.QRコード作成 (rqrcode)
Usersテーブルに新たに、"ine_user_id_token"カラムを追加し、User作成時にSecureRandomnにてランダムな値を保存しました。
そのline_user_id_tokenの値をQRコードに埋め込もうとしましたが、LINEそのものが送られてきたデーターを取得し、webhookにて返すということは出来ませんでした。
↓
そこで、webhookイベントにてSecureRandomnにてランダムな値とLINEIDを別のテーブルに保存し、トーク画面のURLからLINEIDを取得する処理にすることにしました。
(3)webhookイベント後の処理
URL先はLineBotsのnewアクションとしていますので、
def new
if current_user.line_user_id.present?
flash[:notice] = "LINE連携が完了しました"
redirect_to posts_path
else
@line_user_id_token = params[:state]
end
end
このように書きました。params[:state]にてSecureRandomnのランダムな値を取得します。
line_bots/new.html.erb
<div class="container">
<div class="row">
<div class="text-center p-3 m-3">
<%= link_to "LINE連携する", line_bots_path(line_user_id_token: @line_user_id_token), data: { turbo_method: :post }, class: "btn btn-outline-success" %>
</div>
</div>
</div>
line_bots/new.html.erbにてボタンを作成し、
def create
@line_bot_token = LineBotToken.find_by(line_user_id_token: params[:line_user_id_token])
current_user.update(line_user_id: @line_bot_token.line_user_id)
@line_bot_token.destroy
flash[:notice] = "LINE連携が完了しました"
redirect_to posts_path
end
createアクションにてUsersテーブルのline_user_idへ保存し、LineBotTokenのデータは不要の為削除します。
以上になります。