I'm trying to make a direct POST request to Facebook, from my model (user.rb), to send a simple message to this user in Messenger. But I get this error:
{"error":{"message":"(#100) param recipient must be non-empty.","type":"OAuthException","code":100,"fbtrace_id":"F07BNxzgciW"}}
Here is my method:
def send_message(msg)
url = "https://graph.facebook.com/v2.6/me/messages?access_token="+ENV['PAGE_ACCESS_TOKEN']
data = {
'recipient': {
'id': self.facebook_id
},
'message': {
'text': msg
}
}
#data = JSON.pretty_generate(data)
puts data
uri = URI(url)
res = Net::HTTP.post_form(uri, data)
puts res.body
end
Seems like data is not in the right format, so the user id is not beeing recognized.
Uncommenting the #data line I get this error, because data is a string, and not a Hash:
NoMethodError: undefined method `map' for #<String:0x000000034bd248>
This is the request example from Facebook Docs that I'm trying to reproduce:
curl -X POST -H "Content-Type: application/json" -d '{
"recipient": {
"id": "USER_ID"
},
"message": {
"text": "hello, world!"
}
}' "https://graph.facebook.com/v2.6/me/messages?access_token=PAGE_ACCESS_TOKEN"
Try it with this:
Ruby/Rails:
uri = URI("https://graph.facebook.com/v2.6/me/messages?access_token="+ENV['PAGE_ACCESS_TOKEN'])
req = Net::HTTP::Post.new(uri)
req["Accept"] = "application/json"
req["Content-Type"] = "application/json"
req.body = {
'recipient': {
'id': self.facebook_id
},
'message': {
'text': msg
}
}.to_json
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(req)
end
puts res.body
This can be refactored to a function and then be called whenever you need to. This function is a bit more advanced than what needed for the previous request
def http_post(url, payload='', headers={}, auth=false) #basic auth is passed as an array of ['user', 'password']
uri = URI(url)
req = Net::HTTP::Post.new(uri)
headers.each do |k,v|
req[k.to_s] = v
end
req.body = payload.is_a?(Hash) ? payload.to_json : payload.to_s
req.basic_auth(*auth) if auth
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
log_this(req.inspect)
http.request(req)
end
return res
end
# you can now use like:
url = "https://graph.facebook.com/v2.6/me/messages?access_token="+ENV['PAGE_ACCESS_TOKEN']
headers = {
"Accept": "application/json"
"Content-Type": "application/json"
}
payload = {
'recipient': {
'id': self.facebook_id
},
'message': {
'text': msg
}
}
response = http_post(url, payload, options)
With curl you can do the same request with:
curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" -d "{ \"recipient\": { \"id\": \"substitute_with_user_id\" }, \"message\": { \"text\": \"Your message goes here\" } }" https://graph.facebook.com/v2.6/me/messages?access_token=substitute_with_your_access_token
Usually you don't need to escape ( "\" ) the double quotes, instead you can just use single quotes ( ' ) as delimiter of the json body because curl lib will do it for you in most OS where its used, but on windows it seems you need to, and effectively, it will end up being escaped under the hood so that's the correct form I guess.