I don't understand what I do wrong. I want to send a simple request to an API, and it didn't work:
class Paytrace
require 'rest-client'
attr_reader :auth_token, :authorize
def initialize()
#auth_token = auth_token
end
def auth_token
response = RestClient.post 'https://api.paytrace.com/oauth/token', { grant_type: :password, username: "loginname", password: "htmlkoi8r" }
puts response
end
def authorize
headers = {:Authorization => "Bearer #{auth_token['access_token']}"}
response1 = RestClient.get('https://api.paytrace.com/v1/transactions/sale/keyed', headers)
puts response1
end
end
a = Paytrace.new
a.authorize
console.log
lucker#lucker-pc:~/git/paytrace-testh$ ruby integration.rb
{"access_token":"c6d69786f6075633:8647d6c6b6f6968327:092e8cfc553726d2b8198577ea2836f41173aae68a53aa1d2af2b2c7f65dcdc7","token_type":"Bearer","expires_in":7200,"created_at":1556098344}
{"access_token":"c6d69786f6075633:8647d6c6b6f6968327:232c92f977a301d033eec321c3d82b73bb65ebec33f9fcc8f6c2d7575c8b0d88","token_type":"Bearer","expires_in":7200,"created_at":1556098346}
Traceback (most recent call last): 1: from integration.rb:25:in
<main>' integration.rb:16:inauthorize': undefined method `[]' for
nil:NilClass (NoMethodError)
Why is the access_token generated twice?
Why is there an undefined method '[]' for nil:NilClass?
Your method auth_token is not returning a response, but a nil (puts returns nil).
Btw, you don't need attr_reader :authorize since you have a method with that name.
Also, as you are setting attr_reader :auth_token, the method auth_token must be rename (and maybe become private).
Change your code to:
class Paytrace
require 'rest-client'
attr_reader :auth_token
def initialize()
#auth_token = get_auth_token
end
def authorize
headers = {:Authorization => "Bearer #{auth_token['access_token']}"}
RestClient.get('https://api.paytrace.com/v1/transactions/sale/keyed', headers)
end
private
def get_auth_token
RestClient.post 'https://api.paytrace.com/oauth/token', { grant_type: :password, username: "loginname", password: "htmlkoi8r" }
end
end
a = Paytrace.new
puts a.auth_token
puts a.authorize
Seems like there are 3 mistakes in this code the 2 puts. line 12 and 20
and the
headers = {:Authorization => "Bearer #{auth_token['access_token']}"}
should be
headers = {:Authorization => "Bearer #{auth_token[:access_token]}"}
or
headers = {:Authorization => "Bearer #{#auth_token[:access_token]}"}
try this code
class Paytrace
require 'rest-client'
attr_reader :auth_token, :authorize
def initialize()
#auth_token = auth_token
end
def auth_token
response = RestClient.post 'https://api.paytrace.com/oauth/token', { grant_type: :password, username: "loginname", password: "htmlkoi8r" }
# puts response
end
def authorize
headers = {:Authorization => "Bearer #{#auth_token[:access_token]}"}
response1 = RestClient.get('https://api.paytrace.com/v1/transactions/sale/keyed', headers)
# puts response1
end
end
a = Paytrace.new
a.authorize
take care the your response hash if you check is
{:access_token=>"c6d69786f6075633:8647d6c6b6f6968327:092e8cfc553726d2b8198577ea2836f41173aae68a53aa1d2af2b2c7f65dcdc7",
:token_type=>"Bearer",
:expires_in=>7200,
:created_at=>1556098344}
and not
{"access_token":"c6d69786f6075633:8647d6c6b6f6968327:092e8cfc553726d2b8198577ea2836f41173aae68a53aa1d2af2b2c7f65dcdc7","token_type":"Bearer","expires_in":7200,"created_at":1556098344}
Related
I am building a API to a recieve stats for a specific game.
Right now I am able to recieve stats once every time I start my server. After looking up 1 Player I and I'm trying to refresh the page to look up another(right now I am using gets.chomp via console to enter the names) I get the following error:
uninitialized constant SiteController::API
class SiteController < ApplicationController
require_relative '../../lib/api'
def stats
api = API.new(
username: 'someusername',
password: 'somepassword',
token: 'sometoken',
)
puts "Username: "
username = gets.chomp
puts "Platform: "
platform = gets.chomp
#allStats = api.getStats(username, platform)
end
end
api.rb
require 'net/http'
require 'json'
class API
def initialize(auth)
#auth = auth
#Token = getToken['access_token']
end
def TOKEN_URL
'https://antoherlink.com'
end
def EXCHANGE_URL
'https://somelink.com'
end
def LOOKUP_URL(username)
"https://somelink.com{username}"
end
def STATS_URL(id)
"https://somelink.com"
end
def httpGet(url, auth)
uri = URI(url)
req = Net::HTTP::Get.new(uri)
req['Authorization'] = auth
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
JSON.parse(res.body)
end
def httpPost(url, params, auth)
uri = URI(url)
req = Net::HTTP::Post.new(uri)
req.set_form_data(params)
req['Authorization'] = auth
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
JSON.parse(res.body)
end
def getToken
params = {
grant_type: 'password',
includePerms: true,
username: #auth[:username],
password: #auth[:password]
}
httpPost(TOKEN_URL(), params, "basic #{#auth[:token]}")
end
def getExchangeCode
httpGet(EXCHANGE_URL(), "bearer #{getToken['access_token']}")['code']
end
def getToken
params = {
grant_type: 'exchange_code',
includePerms: true,
token_type: 'eg1',
exchange_code: getExchangeCode
}
httpPost(TOKEN_URL(), params, "basic #{#auth[:anothertoken]}")
end
def lookup(username)
httpGet(LOOKUP_URL(username), "bearer #{#Token}")
end
def getRawStats(username)
httpGet(STATS_URL(lookup(username)['id']), "bearer #{#Token}")
end
def getStats(username, platform)
result = decodeRawStats(getRawStats(username), platform)
What did I miss?
Try changing:
class SiteController < ApplicationController
require_relative '../../lib/api'
# ...
end
to
require_dependency 'api'
class SiteController < ApplicationController
# ...
end
I am going to access the Riskscreen api to authenticate users. To test the api I have written a ruby code snippet to make sample POST call to get the number of tokens I have from the Riskscreen api.
My code is:
require 'uri'
require 'net/http'
require 'net/https'
require 'json'
#toSend = {}.to_json
uri = URI.parse("https://api.riskscreen.com/api/v1/user/tokens")
https = Net::HTTP.new(uri.host,uri.port)
https.use_ssl = true
https.verify_mode = OpenSSL::SSL::VERIFY_NONE
header = {'api-key': 'my api key','Content-Type': 'application/json', 'Accept': 'application/json'}
req = Net::HTTP::Post.new(uri.path, header)
req.body = "[ #{#toSend} ]"
res = https.request(req)
puts "------------"
puts "Response #{res.code} #{res.message}: #{res.body}"
But I am getting the following error:
Response 400 Bad Request
If I change the header line to
header = {'api-key'=> 'my-api-key','Content-Type'=> 'application/json', 'Accept'=> 'application/json'}
then I am getting this error:
Response 401 Unauthorized
Sticking with this for a while. Please help me to sort out this.
Header's keys must be String instead of Symbol
header = {'api-key' => 'my api key','Content-Type' => 'application/json', 'Accept' => 'application/json'}
Another issue is net/http is capitalize header automatically, api-key -> Api-Key which cause Authorization Error on your server. One solution is to create new class to wrap api-key to prevent Ruby do that
class HeaderCaseSensitive < String
def capitalize
self
end
def split(*args)
super.each do |str|
HeaderCaseSensitive.new(str)
end
end
def to_s
self
end
end
Then change header:
header = {HeaderCaseSensitive.new('api-key') => 'xxxx','Content-Type' => 'application/json', 'Accept' => 'application/json'}
To sum up, following code will work:
require 'uri'
require 'net/http'
require 'net/https'
require 'json'
class HeaderCaseSensitive < String
def capitalize
self
end
def split(*args)
super.each do |str|
HeaderCaseSensitive.new(str)
end
end
def to_s
self
end
end
#toSend = {}.to_json
uri = URI.parse("https://api.riskscreen.com/api/v1/user/tokens")
https = Net::HTTP.new(uri.host,uri.port)
https.use_ssl = true
https.verify_mode = OpenSSL::SSL::VERIFY_NONE
header = {HeaderCaseSensitive.new('api-key') => 'xxx','Content-Type' => 'application/json', 'Accept' => 'application/json'}
https.set_debug_output($stdout)
req = Net::HTTP::Post.new(uri.path, header)
req.body = "[ #{#toSend} ]"
res = https.request(req)
puts "------------"
puts "Response #{res.code} #{res.message}: #{res.body}"
Can you try remove:
req.body = "[ #{#toSend} ]"
and replace by:
req.set_form_data({})
# or
req.body = "{}"
Sorry, I'm not sure about that.
I thought I was getting closer to wrapping my head around Rails until this challenge. I have an initializer agilecrm.rb - content show below. I am using AgileCRM Ruby code to try and connect my app with AgileCRM system. When using the code below, with the test Create Contact array at the bottom, it successfully creates a contact in my AgileCRM account, so I know at least this part works. What I need to do is create a new AgileCRM user every time I create a new Devise user. I have a feeling that I am looking at this the wrong way and probably need a controller for this, but this is not completely foreign to me, but I still can't figure out when way to go. Thank you.
config/initializers/agilecrm.rb
require 'net/http'
require 'uri'
require 'json'
class AgileCRM
class << self
def api_key=(key)
##api_key = key
end
def domain=(d)
##domain = d
end
def email=(email)
##email = email
end
def api_key
##api_key
end
def domain
##domain
end
def email
##email
end
def request(method, subject, data = {})
path = "/dev/api/#{subject}"
case method
when :get
request = Net::HTTP::Get.new(path)
when :post
request = Net::HTTP::Post.new(path)
request.body = data.to_json
when :put
request = Net::HTTP::Put.new(path)
request.body = data.to_json
when :delete
request = Net::HTTP::Delete.new(path)
else
raise "Unknown method: #{method}"
end
uri = URI.parse("https://#{domain}.agilecrm.com")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request['Content-Type'] = 'application/json'
request['Accept'] = 'application/json'
request.basic_auth AgileCRM.email, AgileCRM.api_key
response = http.request(request)
response.body
end
end
end
AgileCRM.api_key = '*******'
AgileCRM.domain = '*******'
AgileCRM.email = '*******'
# ======================Create Contact====================================
contact_data = '{
"star_value": "4",
"lead_score": "92",
"tags": [
"Lead",
"Likely Buyer"
],
"properties": [
{
"type": "SYSTEM",
"name": "first_name",
"value": "John"
}
]
}'
parsed_contact_data = JSON.parse(contact_data)
print(AgileCRM.request :post, 'contacts', parsed_contact_data)
You might want to move this logic into your User model, and have a after_save hook to push data to agilecrm. Assuming that the Devise user model is called User :
class User < ApplicationRecord
...
after_save :sync_to_agilecrm
def sync_to_agilecrm
# your agilecrm api calls go here
...
end
end
The above should do what you are trying to achieve.
I'm trying to do a request in httparty but it's not working
require 'httparty'
module PvWatch
class Client
include HTTParty
# base_uri ENV["pv_watch_endpoint"]
def login
response = self.class.post('http://pvwatch.xxx.xxx.xxx.net/api/v1/login', options)
end
def options
{
headers: {
'content-type' => 'application/json',
'access-key' => 'FORGET ABOUT THIS',
'authorization' => 'uri=api/v1/login'
},
body: {
username: "case",
password: "123"
}
}
end
end
end
the weird thing is that when i do the request with net/http is working and i don't know what i'm doing wrong with httparty
require 'uri'
require 'net/http'
module PvWatch
class Client
def login
url = URI("http://pvwatch.xxx.xxx.xxx.net/api/v1/login")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Post.new(url)
request["content-type"] = 'application/x-www-form-urlencoded'
request["access-key"] = 'FORGET ABOUT THIS'
request["authorization"] = 'uri=api/v1/login'
request.body = "username=case&password=123"
response = http.request(request)
puts response.read_body
end
end
end
any idea what i'm doing wrong?
Please help me understand, what i'm doing wrong?
I need to make POST request to api from my rails app, i tried to do it firstly with gem "faraday" and then with "net/http". Response from server the same. Account creates, but gives error:
Net::HTTPBadResponse (wrong header line format)
class Connect
require 'uri'
require 'net/http'
require 'net/https'
require 'faraday'
def initialize(email, password, account)
#base_url = "https://example.com"
#client_id = ENV["client_id"]
#client_secret = ENV["client_secret"]
#email = email
#password = password
#account = account
end
# method with net/http
def create_account
#toSend = {
first_name: #account[:first_name],
last_name: #account[:last_name],
client_id: #client_id,
client_secret: #client_secret,
email: #email,
password: #password
}.to_json
uri = URI.parse("#{#base_url}/endclient/api/account")
https = Net::HTTP.new(uri.host,uri.port)
https.use_ssl = true
req = Net::HTTP::Post.new(
uri.path,
initheader = {
'Content-Type' =>'application/json',
'Accept' =>'application/json'
}
)
req.body = "#{#toSend}"
res = https.request(req)
end
# faraday method
def make_account
conn = Faraday.new(:url => "#{#base_url}") do |faraday|
faraday.response :logger
faraday.adapter Faraday.default_adapter
end
params = { first_name: #account[:first_name],
last_name: #account[:last_name],
client_id: #client_id,
client_secret: #client_secret,
email: #email,
password: #password
}.to_json
response = conn.post do |req|
req.url '/endclient/api/account'
req.headers['Content-Type'] = 'application/json'
req.headers['Accept'] = 'application/json'
req.body = params
end
end
end
Done this request with success via Postman, so endpoint of the api is working.
Please help me understand what's wrong with headers ?
Thanks in advance!
UPDATE:
May be problem in this ?
Cannot render console with content type application/jsonAllowed content types: [#<Mime::Type:0x00000003661658 #synonyms=["application/xhtml+xml"], #symbol=:html, #string="text/html">, #<Mime::Type:0x00000003660fc8 #synonyms=[], #symbol=:text, #string="text/plain">, #<Mime::Type:0x0000000365ca68 #synonyms=[], #symbol=:url_encoded_form, #string="application/x-www-form-urlencoded">]
If you want a http lib that easily mixes into a class/module than I would recommend httparty over Faraday or just plain old Net::HTTP.
require 'httparty' # Requires go at the top of the file. Not in class body.
class MyApiClient
include HTTParty
base_uri 'test.example.com'
# Tells Httparty to send JSON for all requests.
format :json
# #see https://robots.thoughtbot.com/ruby-2-keyword-arguments
def initialize(client_id: ENV["client_id"], client_secret: ENV["client_secret"])
#options = {
body: {
client_id: client_id,
client_secret: client_secret
}
}
end
# #return [HTTParty::Response]
def create_account(first_name:, last_name:, email:, password:)
# ActiveSupport method that creates a copy so that we don't
# alter the instance options as a side effect.
opts = #options.deep_dup
opts[:body].merge!(
email: email,
password: password,
first_name: first_name,
last_name: last_name
)
self.class.post('/endclient/api/account', opts)
end
end
The nice thing is that httparty will do all the work with parsing the parameters to and from JSON and sending the correct headers. It also takes care of the dull work of building URI's.
Note that the method signature is slightly different:
client = MyApiClient.new
response = client.create_account(
first_name: 'John',
last_name: 'Doe',
email: 'john.doe#example.com',
password: 'abcd1234'
)
There was a problem on API side, wrong symbols in header.