J'ai eu l'opportunité de développer une fonction d'échange de messages entre un système écrit en Ruby et LINE, un utilisateur généraliste, donc je partagerai les connaissances que j'ai acquises à cette époque.
J'ai également fait une démo d'une application fonctionnelle utilisant Rails, alors voyez ici pour des détails d'implémentation détaillés. Je pense que le contenu de l'article entrera en douceur si vous le demandez.
Un administrateur système (ci-après dénommé «administrateur») et un utilisateur général (ci-après dénommé «utilisateur») créent une fonction d'échange de messages texte via LINE. Étant donné que le système a besoin de connaître les informations LINE de l'utilisateur pour pouvoir communiquer, nous implémenterons également la connexion LINE sur le navigateur.
Après avoir lié les informations LINE de l'utilisateur, lorsque l'utilisateur envoie un message au compte officiel LINE lié à l'administrateur, le message sera envoyé au système par Webhook et sauvegardé dans la base de données à partir de là. L'image est à peu près comme le montre la figure ci-dessous.
L'administrateur peut également envoyer des messages LINE aux utilisateurs via le système. Lorsque vous envoyez un SMS depuis le système, vous pouvez envoyer un message à l'utilisateur cible depuis le compte officiel LINE de l'administrateur via le programme. Une fois envoyé, le message sera enregistré dans la base de données. L'image est la suivante.
Si l'administrateur n'a pas de canal API LINE, il ne sera pas possible de communiquer avec les utilisateurs via LINE, alors créez-le. Faisons-le depuis LINE Developer console. La chaîne dont vous avez besoin pour créer cette fois
Il y en a deux.
L'API de messagerie agit comme un compte LINE officiel. En guise de mise en garde, définissons le ** mode de réponse sur "Bot" **. En mode chat, je peux communiquer depuis le gestionnaire de compte LINE officiel, mais je ne peux pas recevoir de webhooks. Par conséquent, il est nécessaire de l'utiliser en mode Bot car il y a un problème que le système ne peut pas garder un journal de l'interaction. Pour plus de détails sur la façon de le créer, cliquez ici [https://developers.line.biz/ja/docs/messaging-api/getting-started/#%E3%83%81%E3%83%A3%E3%83%8D% E3% 83% AB% E3% 81% AE% E4% BD% 9C% E6% 88% 90) S'il vous plaît. La connexion LINE est littéralement un canal pour utiliser la connexion LINE.
Après la création, créez les données dans la table admins de la base de données. À l'origine, je pense qu'il est bon de s'enregistrer depuis l'écran, mais il est fait pour le porter sur le côté et le piquer directement depuis la console (lors de la mise dans la DB avec le code de production, il est recommandé de le mettre crypté par souci de sécurité. Faire)
create_table "admins", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t|
t.integer "line_messaging_id", null: false #API de messagerie "ID de canal"
t.string "line_messaging_secret", null: false #API de messagerie "Secret de canal"
t.string "line_messaging_token", null: false #API de messagerie "Jeton d'accès au canal"
t.integer "line_login_id", null: false #"ID de chaîne" de la connexion LINE
t.string "line_login_secret", null: false #Connexion LINE "Channel Secret"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
La prochaine fois, je devrai définir des URL du côté console de LINE, donc je vais m'enregistrer. Plus précisément, c'est comme suit.
Il y a certaines choses à prendre en compte lors de l'enregistrement de cette URL. Il a une URL
--https uniquement --localhost non disponible
C'est le but. A ce rythme, le développement local semble difficile. Cependant, en utilisant ngrok, vous pouvez publier temporairement l'URL locale vers l'extérieur, de sorte que vous pouvez confortablement développer localement en enregistrant l'URL créée avec lui. Tu peux le faire. C'est très pratique.
Après avoir créé le chemin de la requête POST pour l'URL Webhook et l'avoir défini sur la console, vérifiez la requête via le bouton «Vérifier». Assurez-vous d'obtenir 200 réponses. Pour plus d'informations [ici](https://developers.line.biz/ja/docs/messaging-api/building-bot/#%E3%82%B3%E3%83%B3%E3%82%BD%E3% 83% BC% E3% 83% AB% E3% 81% A7% E3% 83% 9C% E3% 83% 83% E3% 83% 88% E3% 82% 92% E8% A8% AD% E5% AE% 9A% E3% 81% 99% E3% 82% 8B) S'il vous plaît.
Maintenant que les préparatifs du développement sont terminés, je voudrais continuer à le développer.
Tout d'abord, je voudrais créer une fonction de connexion LINE pour mettre les informations LINE de l'utilisateur nécessaires pour envoyer et recevoir des messages dans la base de données. Cette information LINE est l '"ID utilisateur". Veuillez noter qu'il ne s'agit pas de l'ID de LIGNE utilisé dans la recherche d'ID.
Le flux de connexion est [ici](https://developers.line.biz/ja/docs/line-login/integrate-line-login/#%E3%83%AD%E3%82%B0%E3%82% Ce sera A4% E3% 83% B3% E3% 81% AE% E3% 83% 95% E3% 83% AD% E3% 83% BC), mais si je l'écris à nouveau
redirect_uri
. A ce moment, une chaîne de requête comprenant le code d'autorisation et "état" est également envoyée au système.Regardons le code qui crée l'URL d'autorisation pour l'étape 1.
app/controllers/auth_controller.rb
class AuthController < ApplicationController
def index
admin = Admin.find(params[:admin_id])
state = SecureRandom.hex(32)
session[:state] = state
redirect_to Line::Api::Oauth.new(admin).auth_uri(state)
end
end
/ admin /: admin_id / auth redirige vers l'URL d'autorisation en fonction des informations du compte de connexion LINE de l'administrateur cible.
Étant donné que l'état est nécessaire pour les mesures CSRF, un nombre aléatoire est généré côté application. La valeur est stockée en session (utilisée dans le traitement post-autorisation) et transmise à Line :: Api :: Oauth # auth_uri
. Jetons un coup d'œil au code qu'il contient.
app/models/line/api/oauth.rb
AUTH_URI = 'https://access.line.me/oauth2/v2.1/authorize'
def auth_uri(state)
params = {
response_type: 'code',
client_id: @admin.line_login_id,
redirect_uri: callback_uri,
state: state,
scope: 'openid',
prompt: 'consent', #Option pour vous assurer d'autoriser l'authentification LINE
bot_prompt: 'aggressive' #Une fois connecté, un écran apparaîtra vous demandant si vous souhaitez vous faire des amis avec le compte officiel auquel vous vous êtes lié.
}
# NOTE: https://developers.line.biz/ja/docs/line-login/integrate-line-login/#making-an-authorization-request
"#{AUTH_URI}?#{params.to_query}"
end
Voir ici pour la signification détaillée des paramètres. Personnellement, le paramètre bot_prompt
est pratique, et après la connexion à LINE, l'écran d'ajout d'amis du compte officiel correspondant est également affiché, j'ai donc pensé qu'il serait pratique d'amener des messages entre eux.
Lorsque vous cliquez sur l'URL, vous serez redirigé vers l'écran de connexion comme indiqué dans l'image ci-dessous.
Lorsque la connexion est terminée et l'autorisation terminée, vous serez redirigé vers l'URL de rappel de la connexion LINE que vous avez définie précédemment. Maintenant que nous nous dirigeons vers / admin /: admin_id / callback
, regardons le code correspondant.
app/controllers/callback_controller.rb
class CallbackController < ApplicationController
def index
admin = Admin.find(params[:admin_id])
#Lancer une exception si les états sont différents
raise Line::InvalidState unless params[:state] == session[:state]
line_user_id = Line::Api::Oauth.new(admin).line_user_id(params[:code])
User.create!(line_user_id: line_user_id)
render plain: 'Coopération LINE terminée!', status: :ok
end
end
Les mesures CSRF sont prises en comparant la valeur de l'état qui vient après l'autorisation avec la valeur de l'état de la session qui a été précédemment entrée. Après cela, obtenez l'ID utilisateur LINE. Une fois obtenu, stockez-le dans la base de données. Jetons un coup d'œil au code d'acquisition de l'ID utilisateur.
app/models/line/api/oauth.rb
def line_user_id(code)
verify_id_token(access_token_data(code))['sub']
end
def access_token_data(code)
req_body = {
grant_type: 'authorization_code',
code: code,
redirect_uri: callback_uri, # NOTE:Elle est comparée à l '"URL de rappel" définie dans la console du canal de connexion LINE.
client_id: @admin.line_login_id,
client_secret: @admin.line_login_secret
}
# NOTE: https://developers.line.biz/ja/docs/line-login/integrate-line-login/#get-access-token
res = conn.post do |req|
req.url '/oauth2/v2.1/token'
req.headers['Content-Type'] = 'application/x-www-form-urlencoded'
req.body = req_body
end
JSON.parse(handle_error(res).body)
end
def verify_id_token(access_token_data)
req_body = {
id_token: access_token_data['id_token'],
client_id: @admin.line_login_id
}
# NOTE: https://developers.line.biz/ja/reference/social-api/#verify-id-token
res = conn.post do |req|
req.url '/oauth2/v2.1/verify'
req.body = req_body
end
JSON.parse(handle_error(res).body)
end
ʻAccess_token_data` accède à API d'acquisition de jetons d'accès pour renvoyer des informations, puis À l'API sociale API de vérification de jeton d'identification et réussissez, vous obtiendrez votre identifiant d'utilisateur.
Une chose à garder à l'esprit est que l'API d'acquisition de jetons d'accès transmet redirect_uri
, qui devrait être exactement le même que le redirect_uri
défini dans l'URI d'autorisation. Vous ne pouvez pas faire grand-chose, mais pour diverses raisons, si vous voulez passer quelque chose comme paramètre de requête à redirect_uri
lors de la création d'une URL d'autorisation et l'obtenir avec un rappel, l'API d'acquisition de jeton d'accès comprenant ce paramètre de requête Ne pas le transmettre à redirect_uri
entraînera une erreur.
Maintenant que l'utilisateur a pu se connecter avec le compte officiel LINE de l'administrateur, je souhaite recevoir le message LINE envoyé par l'utilisateur dans le système suivant.
Étant donné que l'URL du chemin de / admin /: admin_id / webhook
est spécifiée dans l'URL du Webhook de l'API de messagerie, la demande sera envoyée chaque fois qu'un événement (ajouter un ami, bloquer un message, etc.) se produit dans le compte officiel. Devenir.
Ainsi, si l'événement qui a envoyé le message à partir de cette demande && la personne qui l'a envoyé est l'ID utilisateur LINE ** enregistré dans la base de données, si vous enregistrez le message dans la base de données, les messages LINE de l'utilisateur seront collectés. Vous pouvez.
Le code du contrôleur Webhook est ci-dessous.
app/controllers/webhook_controller.rb
class WebhookController < ApplicationController
protect_from_forgery with: :null_session
def create
admin = Admin.find(params[:admin_id])
bot = Line::Api::Bot.new(admin)
body = request.body.read
raise Line::InvalidSignatureError unless bot.validate_signature?(body, request.env['HTTP_X_LINE_SIGNATURE'])
events = bot.parse_events_from(body)
events.each do |event|
case event
when Line::Bot::Event::Message
Line::SaveReceivedMessage.new(admin).call(event)
end
end
render plain: 'success!', status: :ok
end
end
Étant donné que la demande provient de l'extérieur, invalidez le jeton CSRF. Vous devez également faire Vérification de la signature pour déterminer si la demande provient de la plate-forme LINE. C'est un peu compliqué, mais c'est fait avec un gem appelé line-bot-sdk-ruby, alors utilisons-le.
Après vérification, déterminez à quoi ressemble l'événement. Je vais l'utiliser car la gemme analysera également les informations d'événement du corps de la requête.
Je pense qu'il est simple de brancher des événements avec une déclaration de cas. Puisque Line :: Bot :: Event :: Message
est l'événement lorsque le message arrive, le processus d'enregistrement du message est inséré à ce moment. Le code est ci-dessous.
app/models/line/save_received_message.rb
module Line
class SaveReceivedMessage
def initialize(admin)
@admin = admin
end
def call(event)
user = User.find_by(line_user_id: event['source']['userId'])
resource = MessageText.new(content: event.message['text'])
Message.create!(sendable: user, receivable: @admin, resource: resource) if user.present?
end
end
end
Voir ici pour le contenu de l'objet événement.
Enfin, vérifiez le fonctionnement. Lorsque vous envoyez un message
Vous pouvez voir que la demande est ignorée et que l'enregistrement est enregistré. Le système peut maintenant recevoir le message LINE de l'utilisateur et le mettre dans la base de données.
Ensuite, nous examinerons la transmission des messages Système-> LIGNE de l'utilisateur, qui est l'opposé de la précédente. Vous n'avez pas besoin d'utiliser Webhook, appuyez simplement sur API pour envoyer un message push et vous avez terminé.
app/models/line/save_sent_message.rb
module Line
class SaveSentMessage
def initialize(admin)
@admin = admin
end
def call_with_text(user:, text:)
user = User.find_by(line_user_id: user.line_user_id)
if user.present?
Line::Api::Push.new(@admin).call_with_text(user: user, text: text)
resource = MessageText.new(content: text)
Message.create!(sendable: @admin, receivable: user, resource: resource)
end
end
end
end
app/models/line/api/push.rb
module Line::Api
class Push < Base
def call_with_text(user:, text:)
call(user: user, resource: Message::Text.new([text]))
end
private
def call(user:, resource:)
req_body = {to: user.line_user_id}.merge(resource.request_body)
# NOTE: https://developers.line.biz/ja/reference/messaging-api/#send-push-message
res = conn.post do |req|
req.url '/v2/bot/message/push'
req.headers['Content-Type'] = 'application/json'
req.headers['Authorization'] = "Bearer #{@admin.line_messaging_token}"
req.body = req_body.to_json
end
handle_error(res)
end
end
end
C'est un contrôle de fonctionnement. Portez-le sur le côté et frappez l'accord de la console.
Un enregistrement a été ajouté.
Un message a été envoyé à LINE!
Avec ce qui précède, il est possible de communiquer entre l'utilisateur et le système et de laisser le contenu. Je pense que ce sera plus compliqué dans un vrai système, mais j'espère que cela vous aidera à mettre en œuvre quelque chose: priez:
Recommended Posts