shokun1209
@shokun1209 (s shoya)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

ruby on rails / line bot

解決したいこと

こちらの記事を実践してみようと試みているのですが、LineBotからwebhook検証をかけると下記のエラーが発生してしまいます。

発生している問題error422.png

毎度herokuへpushするのもしんどいのでngrokを使用しております。

ターミナル上でも下記のエラーが検証毎に出力される状況です。

POST /callback                 422 Unprocessable Entity

最終的にコピペを行いましたがやはり解決されず悩んでおります。。。

# webhook_controller.rb
require 'line/bot'

class WebhookController < ApplicationController
  before_action :set_line_client

  CHANNEL_SECRET = ENV['CHANNEL_SECRET'] # 記録しておいたChannel Secret
  CHANNEL_ACCESS_TOKEN = ENV['CHANNEL_ACCESS_TOKEN'] # 記録しておいたアクセストークン

  def callback
    body = request.body.read

    unless @client.validate_signature(body, request.env['HTTP_X_LINE_SIGNATURE'])
      error 400 do 'Bad Request' end
    end

    event = @client.parse_events_from(body)[0]
    message = { text: nil }

    case event.type
    # 画像か動画なら登録する
    when "image", "video"
      temp = Tempfile.new("example").binmode.tap do |file|
        file.write @client.get_message_content(event.message['id']).body
      end
      if Photo.create(image: temp, uploader_id: find_or_create_uploader.id, photo_date: Time.zone.today, content_type: event.type)
        type_str = event.type == "image" ? "画像" : "動画"
        message = { type: 'text', text: "#{type_str}を登録しました。" }
      end
    end

    # Botを介してLineへメッセージ送信
    if message[:text].present?
      @client.reply_message(event['replyToken'], message)
    end

    # webからは何も返さない
    render :nothing => true, status: :ok
  end

  private

  # メッセージを取扱いやすくしてくれるclientをセット
  def set_line_client
    @client ||= Line::Bot::Client.new { |config|
      config.channel_secret = CHANNEL_SECRET
      config.channel_token = CHANNEL_ACCESS_TOKEN
    }
  end

  # Uploaderを見つけるor登録する
  def find_or_create_uploader
    line_id = params[:events][0][:source][:userId]
    uploader = Uploader.find_by(line_id: line_id)
    unless uploader
      uploader = Uploader.create(line_id: line_id, token: SecureRandom.uuid, name: line_name(line_id))
    end
    uploader
  end

  # プロフィールからLineの名前を取ってくる
  def line_name(line_id)
    response = @client.get_profile(line_id)
    case response
    when Net::HTTPSuccess then
      return JSON.parse(response.body)['displayName']
    end
  end
end

こちらに記述のある内容については全てコピペ致しました。
逆に記述のない事はmigrationファイル以外記述しておりません

カラム型はコントローラーの記述を見て自身で設定したのでここがおかしいのかもしれません

# photos テーブル
class CreatePhotos < ActiveRecord::Migration[6.0]
  def change
    create_table :photos do |t|
      t.string :image
      t.date :photo_date
      t.references :uploader
      t.timestamps
    end
  end
end
# uploader テーブル
class CreateUploaders < ActiveRecord::Migration[6.0]
  def change
    create_table :uploaders do |t|
      t.string :line_id
      t.string :token
      t.string :name
      t.timestamps
    end
  end
end

自分で試したこと

丸一日色々な記事で類似症状を探しては試行しましたが全く結果が変わりません。。。
(そもそも何が悪いのか分かってない)

何卒よろしくお願い致します:pray:

0

1Answer

rails で 422 Unprocessable Entity が返るのは、おそらく InvalidAuthenticityTokenInvalidCrossOriginRequest が発生している場合ではないかと思います。

CSRF 対策を入れてみてはいかがでしょうか?(InvalidCrossOriginRequest が発生している想定)

WebhookController に以下の行を追加したら変わらないでしょうか。

  protect_from_forgery :except => [:callback]

もう一つ気になるのはLine API には、場合によっては events が 0 件のことがあるとの記載があり

これでエラーになる可能性もあるかもしれません(その場合には 500 Internal Server Error な気がしますが)

1Like

Comments

  1. @shokun1209

    Questioner

    大変わかりやすく説明頂きありがとうございます!!

    ```ruby
    protect_from_forgery :except => [:callback]

    ```

    ご教授頂いた通り上記を記述してみたところ、@yoshi389111様の予想通り500 Internal Server Error が出現しました!!

    herokuログで確認したところ、eventsにてエラーが起きている事も確認できました

    実際に linebot から画像を送信してみると日付の取得でエラーが起きている様子も見受けられたので、ここを解消できれば先へ進めそうです!

    もうダメだと思っていましたが、また前を向く事ができました。

Your answer might help someone💌